因爲公司產品(基於vue.js)須要,要實現一個樹形表格的功能,百度、google找了一通,並無發現很靠譜的,也不是很靈活。因此就用vue本身擼了一個,還望你們多多指教。javascript
vue子組件的遞歸實現及相關樣式的實現
index.vue頁面實現業務邏輯代碼,好比樹表格上面的一些操做按鈕的實現及數據獲取。css
<template>
<div class="contains">
<h1>樹表格實現</h1>
<tree-table ref="recTree" :list.sync="treeDataSource" @actionFunc="actionFunc" @deleteFunc="deleteFunc" @orderByFunc="orderByFunc"></tree-table>
</div>
</template>
<script> import treeTable from '@/components/tree-table.vue' export default { data() { return { list: [], // 請求原始數據 treeDataSource: [] // 組合成樹表格接收的數據 } }, components: { treeTable }, methods: { orderByFunc(val) { alert('排序') alert(val) }, actionFunc(m) { alert('編輯') }, deleteFunc(m) { alert('刪除') } } } </script>
複製代碼
原始數據`list`:是不包含子數據的數據結構,即沒有層級結構,例如:
[{id:111,parentId:0,name:'父及'},{id:111,parentId:111,name:'子級'}...],經過parentId來獲取對應父子層級結構
`treeDataSource`:是樹表格須要的數據結構,例如:
[{id:0,name:'父及',children:[{id:10,name:'子級',children:[]}]},...]
複製代碼
若是後臺返回給你的是原始數據格式,就能夠用下面方法封裝成樹表格可使用的數據結構:html
getTreeData() {
// 取父節點
let parentArr = this.list.filter(l => l.parentId === 0)
this.treeDataSource = this.getTreeData(this.list, parentArr)
},
// 這裏處理沒有children結構的數據
getTreeData(list, dataArr) {
dataArr.map((pNode, i) => {
let childObj = []
list.map((cNode, j) => {
if (pNode.Id === cNode.parentId) {
childObj.push(cNode)
}
})
pNode.children = childObj
if (childObj.length > 0) {
this.getTreeData(list, childObj)
}
})
return dataArr
}
複製代碼
tree-table.vue頁面。此頁面是實現樹表格的關健頁面。主要代碼以下:vue
<template>
<div class="tree-table">
<div class="tree-head">
<table>
<tr>
<td class="td1">職位名稱</td>
<td class="td2">負責人</td>
<td class="td3" @click="isDesc=!isDesc">
建立時間
<div class="arrow">
<span class="up-arrow" :class="{'sort':isDesc}"></span>
<span class="down-arrow" :class="{'sort':!isDesc}"></span>
</div>
</td>
<td class="td4">工做經驗</td>
<td class="td5">發佈時間</td>
<td class="td6">操做</td>
</tr>
</table>
</div>
<div id="scrollWrap" class="tree-wrap">
<div class="tree-body">
<table v-if='treeDataSource.length>0'>
<tbody>
<tr>
<td>
<tree-item v-for="(model,i) in treeDataSource" :key="'root_node_'+i" :root="0" :num="i" @actionFunc="actionFunc" @deleteFunc="deleteFunc" :nodes="treeDataSource.length" :trees.sync="treeDataSource" :model.sync="model">
</tree-item>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
複製代碼
首先這裏的子組件tree-item
沒有在頁面上有引入,可是也能夠正常使用。這裏就是關健點,由於這個子組件是須要遞歸實現,因此,須要動態註冊到當前組件中。代碼以下(因爲代碼太多,先貼圖說明吧,點擊這裏能夠看源碼):java
這裏子組件看起來是否是挺奇怪的,可是爲了遞歸他自己,暫時也只想到這種辦法。若是有更好的辦法,歡迎留言指正。
那麼,樹表格的結構實如今哪裏呢??對,就是在子組件的模版(template
)裏面,這裏就不貼代碼了,能夠移步到源碼查看。
node
components: {
treeItem: () => import('./tree-item.vue')
}
複製代碼
補充一點:不要只看js部分,css部分纔是這個樹表格的關健所在。固然裏面我採用了大量的計算屬性去判斷各類樣式的展現,還有一種方法,就是在
initTreeData
方法裏面去實現,這個方法就是處理或添加一些咱們樹表格所使用的信息。好比我如今在裏面實現的層級線的偏移量m.bLeft = level === 1 ? 34 : (level - 2) * 16 + 34
這個計算若是沒有看明白,能夠留言。github
最後,此篇乃個人開篇之做,若有問題,還請多多包含,多多指教!!!順便給我很久沒有更新的博客打個廣告, 歡迎點擊(一座城池)bash
參考資源隔壁家的老黃數據結構