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

基於vue.js實現樹形表格的封裝(vue-tree-table)

前言

因爲公司產品(基於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

  • 源碼地址github,歡迎star。
參考資源 隔壁家的老黃
相關文章
相關標籤/搜索