因爲公司產品(基於vue.js)須要,要實現一個 樹形表格的功能,百度、google找了一通,並無發現很靠譜的,也不是很靈活。因此就用vue本身擼了一個,還望你們多多指教。
vue子組件的遞歸實現及相關樣式的實現
index.vue頁面實現業務邏輯代碼,好比樹表格上面的一些操做按鈕的實現及數據獲取。
<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:[]}]},...]
若是後臺返回給你的是原始數據格式,就能夠用下面方法封裝成樹表格可使用的數據結構:
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頁面。此頁面是實現樹表格的關健頁面。主要代碼以下:
<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
沒有在頁面上有引入,可是也能夠正常使用。這裏就是關健點,由於這個子組件是須要遞歸實現,因此,須要動態註冊到當前組件中。代碼以下(因爲代碼太多,先貼圖說明吧,點擊這裏能夠看源碼):css
這裏子組件看起來是否是挺奇怪的,可是爲了遞歸他自己,暫時也只想到這種辦法。若是有更好的辦法,歡迎留言指正。
那麼,樹表格的結構實如今哪裏呢??對,就是在子組件的模版(template
)裏面,這裏就不貼代碼了,能夠移步到源碼查看。
html
收到 favourli的指正,現已將原有寫法更新,採用 遞歸組件來實現,這樣頁面看起來就更清晰。
components: { treeItem: () => import('./tree-item.vue') }
補充一點:不要只看js部分,css部分纔是這個樹表格的關健所在。固然裏面我採用了大量的計算屬性去判斷各類樣式的展現,還有一種方法,就是在initTreeData
方法裏面去實現,這個方法就是處理或添加一些咱們樹表格所使用的信息。好比我如今在裏面實現的層級線的偏移量m.bLeft = level === 1 ? 34 : (level - 2) * 16 + 34
這個計算若是沒有看明白,能夠留言。
最後,此篇乃個人開篇之做,若有問題,還請多多包含,多多指教!!!順便給我很久沒有更新的博客打個廣告,
歡迎點擊(<span style="color:#f24c27;font-weight:600">一座城池</span>)vue
參考資源 隔壁家的老黃