我開源了基于Vue的組織架構(gòu)樹組件
開門見山
Demo 演示地址:http://www.longstudy.club/vue-okr-tree-doc/index.html
github 地址:https://github.com/qq449245884/vue-okr-tree
項目背景
因為最近公司需要做一個OKR,OKR 里面有個對齊視圖,是一個數(shù)型結(jié)構(gòu),如下圖所示:
就拿我 小智 來說,如果有人對齊我的 KR 就放到我的右邊,如果是我對齊了誰的 KR,就放到我的左邊,類似一個上下級的關系,所以這里我用兩棵樹來表示左邊與右邊的關系。
在GitHub上找了半天,這類組件不多,也沒有符合業(yè)務需求的組件,所以決定自己造輪子!
分析
- 既然是樹,那么每個節(jié)點都應該是相同的組件
- 節(jié)點下面套節(jié)點,所以節(jié)點組件應該是一個遞歸組件
- 整棵樹應該有一個全局的狀態(tài),用來管理從外部傳入的值以及向外部提供的屬性和方法。
- 每相樹節(jié)點應該也要有一個對應的節(jié)點狀態(tài),來管理節(jié)點自身屬性和方法。
實現(xiàn)思路
遞歸組件
對于遞歸組件,Vue 官方文檔是這樣說的:
組件在它的模板內(nèi)可以遞歸地調(diào)用自己。不過,只有當它有 name 選項時才可以這么做。
這里我用 OkrTreeNode.vue 來表示樹的節(jié)點,里面是這樣用遞歸,下面是該組件簡定:
- <template>
- <OkrTreeNode
- v-for="child in leftChildNodes"
- :node="child"
- ></OkrTreeNode>
- </template>
- export default {
- name: 'OkrTreeNode'
- }
遞歸組件的使用需要注意的兩點是組件里面要有組件name 以及結(jié)束遞歸的條件。
樹的狀態(tài)
對于樹的狀態(tài),我用一個 TreeStore 類來表示,該實現(xiàn)方式主要是參考 ElementUI 中的 tree 組件。TreeStore 中的屬性就表示我外部傳入的 pros 或者 attr 或者 事件和方法,都在這個對象里面管理,具體的代碼可以看這里:
https://github.com/qq449245884/vue-okr-tree/blob/main/src/lib/vue-okr-tree/model/tree-store.js
節(jié)點的狀態(tài)
對于節(jié)點的狀態(tài),我用一個 Node 對象來表示,具體的代碼可以看下面這個地址,這里就不展開說了:
https://github.com/qq449245884/vue-okr-tree/blob/main/src/lib/vue-okr-tree/model/node.js
Demo 演示
基礎用法
基礎的樹形結(jié)構(gòu)展示,默認方式垂直方向。
水平方向
將 direction 屬性設置為 horizontal 就可以展示水平方向。
節(jié)點是否可被展開
節(jié)點可被展開,默認是不展開,通過show-collapsable設置節(jié)點可被展開。
節(jié)點默認全部展開
通過設置 default-expand-all 默認展開所有節(jié)點,該參數(shù)只有在 show-collapsable為true 時有效
可將 Tree 的某些節(jié)點設置為默認展開
通過 default-expanded-keys 設置默認展開的節(jié)點。需要注意的是,此時必須設置 node-key ,其值為節(jié)點數(shù)據(jù)中的一個字段名,該字段在整棵樹中是唯一的。
節(jié)點的樣式可自行設置節(jié)點的默認樣式和選中的樣式。
通過 label-class-name 設置節(jié)點的樣式,支持字符和函數(shù)方式。通過 current-lable-class-name 設置當前節(jié)點選中的樣式,支持字符和函數(shù)方式。
節(jié)點自定義內(nèi)容
可自行設置節(jié)點內(nèi)容。通過 render-content 渲染節(jié)點內(nèi)容。
OKR 展示模式
該模式的出現(xiàn),是為了實現(xiàn)跟飛書OKR 展示的視圖一樣效果,所以在 Tree 的模式下,擴展成左右兩棵子樹。該模式必須設置 onlyBothTree ,以及通過 leftData表示左子數(shù)的結(jié)構(gòu)。
OKR 展示模式之自定義節(jié)點內(nèi)容
與上常規(guī) Tree 一樣,我們也可以通過自定義渲染函數(shù)來制定節(jié)點的內(nèi)容。
通過 render-content 渲染節(jié)點內(nèi)容,通過返回 node 中的 isLeftChild 判斷是否是左邊的樹。
節(jié)點過濾(不可展開)及支持的方法
通過關鍵字過濾樹節(jié)點,在需要對節(jié)點進行過濾時,調(diào)用 Tree 實例的 filter 方法,參數(shù)為關鍵字。需要注意的是,此時需要設置 filter-node-method ,值為過濾函數(shù)。
節(jié)點過濾(可被展開)
通過關鍵字過濾樹節(jié)點,在需要對節(jié)點進行過濾時,調(diào)用 Tree 實例的 filter 方法,參數(shù)為關鍵字。需要注意的是,此時需要設置 filter-node-method ,值為過濾函數(shù)。
支持的事件(不可展開)
不可展開時支持的事件有 節(jié)點點擊 和 鼠標右鍵點擊。
支持的事件(可被展開)
可展開時支持的事件有 節(jié)點點擊、鼠標右鍵點擊,節(jié)點的展開以及節(jié)點的關閉。
Attributes
參數(shù) | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
data | 展示數(shù)據(jù) | array | — | — |
direction | 樹的展開方向 | String | horizontal / vertical | vertical |
onlyBothTree | 子樹在根節(jié)點左右兩邊展開,該模式只有在 direction 為 horizontal 有效,且必須提供 leftData 數(shù)據(jù) | Boolean | — | false |
leftData | 展示左子數(shù)的數(shù)據(jù),該屬性于在 onlyBothTree 模式啟用 | array | — | — |
label-width | 節(jié)點的寬度,默認為自動寬度。如果 label-width 為 number 類型,單位 px;如果 label-width 為 string 類型,則這個寬度會設置為 節(jié)點 的 style.width 的值,節(jié)點的寬度會受控于外部樣式 | string/number | — | — |
label-height | 節(jié)點的高度,默認為自動高度。如果 label-height 為 number 類型,單位 px;如果 label-height 為 string 類型,則這個高度會設置為 節(jié)點 的 style.height 的值,節(jié)點的高度會受控于外部樣式 | string/number | — | — |
label-class-name | 節(jié)點 className 的回調(diào)方法,也可以使用字符串為所有的節(jié)點設置一個固定的 className | Function(node)/String | — | — |
current-lable-class-name | 當前選中節(jié)點的樣式 | Function(node)/String | — | — |
show-collapsable | 節(jié)點是否可被展開 | Boolean | — | false |
default-expand-all | 是否默認展開所有節(jié)點,該參數(shù)只有在 show-collapsable 為 true 時有效 | Boolean | — | false |
render-content | 樹節(jié)點的內(nèi)容區(qū)的渲染 Function | Function(h, node) | — | — |
props | 配置選項,具體看下表 | object | — | — |
node-key | 每個樹節(jié)點用來作為唯一標識的屬性,整棵樹應該是唯一的 | String | — | — |
default-expanded-keys | 默認展開的節(jié)點的 key 的數(shù)組(需要注意的是,此時必須設置node-key,其值為節(jié)點數(shù)據(jù)中的一個字段名,該字段在整棵樹中是唯一的。) | array | — | — |
filter-node-method | 對樹節(jié)點進行篩選時執(zhí)行的方法,返回 true 表示這個節(jié)點可以顯示,返回 false 則表示這個節(jié)點會被隱藏 | Function(value, data, node) | — | — |
props
參數(shù) | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
label | 指定節(jié)點標簽為節(jié)點對象的某個屬性值 | string, function(data, node) | — | — |
children | 指定節(jié)點標簽為節(jié)點對象的某個屬性值 | string | — | — |
## Events
事件名稱 | 說明 | 回調(diào)參數(shù) |
---|---|---|
node-click | 節(jié)點被點擊時的回調(diào) | 共三個參數(shù),依次為:傳遞給 data 屬性的數(shù)組中該節(jié)點所對應的對象、節(jié)點對應的 Node、節(jié)點組件本身。 |
node-expand | 節(jié)點被展開時觸發(fā)的事件 | 共三個參數(shù),依次為:傳遞給 data 屬性的數(shù)組中該節(jié)點所對應的對象、節(jié)點對應的 Node、節(jié)點組件本身 |
node-collapse | 節(jié)點被關閉時觸發(fā)的事件 | 共三個參數(shù),依次為:傳遞給 data 屬性的數(shù)組中該節(jié)點所對應的對象、節(jié)點對應的 Node、節(jié)點組件本身 |
node-contextmenu | 當某一節(jié)點被鼠標右鍵點擊時會觸發(fā)該事件 | 共四個參數(shù),依次為:event、傳遞給 data 屬性的數(shù)組中該節(jié)點所對應的對象、節(jié)點對應的 Node、節(jié)點組件本身。 |
方法
方法名 | 說明 | 回調(diào)參數(shù) |
---|---|---|
filter | 對樹節(jié)點進行篩選操作 | 接收一個任意類型的參數(shù),該參數(shù)會在 filter-node-method 中作為第一個參數(shù) |
getNode | 根據(jù) data 或者 key 拿到 Tree 組件中的 node,使用此方法必須設置 node-key 屬性 | (data) 要獲得 node 的 key 或者 data |
setCurrentNode | 通過 node 設置某個節(jié)點的當前選中狀態(tài),使用此方法必須設置 node-key 屬性 | (node) 待被選節(jié)點的 node |
setCurrentKey | 通過 key 設置某個節(jié)點的當前選中狀態(tài),使用此方法必須設置 node-key 屬性 | (key) 待被選節(jié)點的 key,若為 null 則取消當前高亮的節(jié)點 |
getCurrentKey | 獲取當前被選中節(jié)點的 key,使用此方法必須設置 node-key 屬性,若沒有節(jié)點被選中則返回 null | — |
getCurrentNode | 獲取當前被選中節(jié)點的 data,若沒有節(jié)點被選中則返回 null | — |
remove | 刪除 Tree 中的一個節(jié)點,使用此方法必須設置 node-key 屬性 | (data) 要刪除的節(jié)點的 id 或者 data 或者 node |
append | 為 Tree 中的一個節(jié)點追加一個子節(jié)點 | (data, parentNode) 接收兩個參數(shù),1. 要追加的子節(jié)點的 data 2. 子節(jié)點的 parent 的 data、key 或者 node |
insertBefore | 為 Tree 的一個節(jié)點的前面增加一個節(jié)點 | (data, refNode) 接收兩個參數(shù),1. 要增加的節(jié)點的 data 2. 要增加的節(jié)點的后一個節(jié)點的 data、key 或者 node |
insertAfter | 為 Tree 的一個節(jié)點的后面增加一個節(jié)點 | (data, refNode) 接收兩個參數(shù),1. 要增加的節(jié)點的 data 2. 要增加的節(jié)點的前一個節(jié)點的 data、key 或者 node |
瀏覽器支持情況
Modern browsers and Internet Explorer 10+.
如果你覺得還不錯的話,還請幫忙在 github 上給個 star,如果你覺得哪些需要優(yōu)化的可以到 github 上提個 PR。
本文轉(zhuǎn)載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉(zhuǎn)載本文請聯(lián)系大遷世界公眾號。