基於vue.js實現樹形表格的封裝

前言

因爲公司產品(基於vue.js)須要,要實現一個樹形表格的功能,百度、google找了一通,並無發現很靠譜的,也不是很靈活。因此就用vue本身擼了一個,還望你們多多指教。javascript

主要技術點:vue子組件的遞歸實現及相關樣式的實現

樹形表格實現

  • 效果圖(Demo)
  • 主要代碼

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

  • 感謝

收到favourli的指正,現已將原有寫法更新,採用遞歸組件來實現,這樣頁面看起來就更清晰。git

components: {
			treeItem: () => import('./tree-item.vue')
	}
複製代碼

補充一點:不要只看js部分,css部分纔是這個樹表格的關健所在。固然裏面我採用了大量的計算屬性去判斷各類樣式的展現,還有一種方法,就是在initTreeData方法裏面去實現,這個方法就是處理或添加一些咱們樹表格所使用的信息。好比我如今在裏面實現的層級線的偏移量m.bLeft = level === 1 ? 34 : (level - 2) * 16 + 34 這個計算若是沒有看明白,能夠留言。github

最後,此篇乃個人開篇之做,若有問題,還請多多包含,多多指教!!!順便給我很久沒有更新的博客打個廣告, 歡迎點擊(一座城池bash

  • 源碼地址github,歡迎star。

參考資源隔壁家的老黃數據結構

相關文章
相關標籤/搜索