優(yōu)雅的將ElementUI表格變身成樹(shù)形表格的方法步驟
由于ElementUI目前還未開(kāi)發(fā)樹(shù)形表格組件,也參閱了網(wǎng)絡(luò)上部分基于ElementUI表格封裝的開(kāi)源樹(shù)形組件,如果想進(jìn)行二次開(kāi)發(fā)的話都不太理想,所以就萌生了自行開(kāi)發(fā)樹(shù)形表格。
本示例提供開(kāi)發(fā)思路,移除了多余的樣式,比較適合新手入門(mén)學(xué)習(xí),如果應(yīng)用于實(shí)際項(xiàng)目還請(qǐng)自行封裝。
目前還僅僅實(shí)現(xiàn)了視覺(jué)的樹(shù)結(jié)構(gòu)的層級(jí)效果和控制結(jié)構(gòu)的顯示隱藏,后續(xù)還會(huì)進(jìn)行不斷的完善和優(yōu)化,有必要的話會(huì)對(duì)組件進(jìn)行二次封裝,有點(diǎn)在重復(fù)造論的感覺(jué)哈。
效果圖
完整代碼
頁(yè)面(tree-table.vue)
<template> <div> TreeTable <el-table :data="list" :row-style="tableRowStyle" border> <el-table-column type="selection" width="55"></el-table-column> <el-table-column prop="id" label="ID" width="180"> <template slot-scope="scope"> <span class="collapse" :class="collapseClass(scope.row)" :style="tableRowPaddingStyle(scope.row)" @click="handleCollapseClick(scope.row)"> </span> <span>{{ scope.row.id }}</span> </template> </el-table-column> <el-table-column prop="name" label="NAME"></el-table-column> </el-table> </div> </template> <script lang="ts"> import {Component, Vue} from 'vue-property-decorator' // 引入兩個(gè)封裝好的工具方法 import { arrayToTree } from './utils/array.js' import { ergodicTree } from './utils/tree.js' @Component export default class TreeTable extends Vue { private list: object[] = []; private tree: object[] = []; created() { // 準(zhǔn)備一組含有父子級(jí)關(guān)系的一維數(shù)組方便示例測(cè)試 // 在實(shí)際項(xiàng)目應(yīng)用中,理應(yīng)通過(guò)后端接口返回 let _list = [ { id: 'a', pid: '', name: '部門(mén)a', children: [] }, { id: 'a1', pid: 'a', name: '子部門(mén)a1', children: [] }, { id: 'a2', pid: 'a', name: '子部門(mén)a2', children: [] }, { id: 'a2-1', pid: 'a2', name: '子部門(mén)a2-1', children: [] }, { id: 'a2-2', pid: 'a2', name: '子部門(mén)a2-2', children: [] }, { id: 'a3', pid: 'a', name: '子部門(mén)a3', children: [] }, { id: 'a3-1', pid: 'a3', name: '子部門(mén)a3-1', children: [] }, { id: 'b', pid: '', name: '部門(mén)b', children: [] }, { id: 'b1', pid: 'b', name: '子部門(mén)b1', children: [] }, { id: 'c', pid: '', name: '部門(mén)c', children: [] }, ]; // 將一維數(shù)組轉(zhuǎn)成樹(shù)形結(jié)構(gòu)并存儲(chǔ)于tree變量 this.tree = arrayToTree(_list); // 考慮到實(shí)際應(yīng)用過(guò)程中接口返回的數(shù)據(jù)是無(wú)序的,所以我們對(duì)tree進(jìn)行先序遍歷將節(jié)點(diǎn)一一插入到list變量 this.list = []; ergodicTree(this.tree, (node: any) => { this.list.push(node); // 遍歷過(guò)程中并對(duì)每個(gè)節(jié)點(diǎn)掛載open和show屬性 // open:控制節(jié)點(diǎn)的打開(kāi)和關(guān)閉 // show:控制節(jié)點(diǎn)的顯示和隱藏 this.$set(node, 'open', true); this.$set(node, 'show', true) }) } // 控制行的顯示和隱藏 tableRowStyle(scope: any) { return { 'display': scope.row.show ? '' : 'none' } } // 通過(guò)每個(gè)節(jié)點(diǎn)的深度,設(shè)置行的縮進(jìn)實(shí)現(xiàn)視覺(jué)上的層級(jí)效果 tableRowPaddingStyle(row: any) { return { 'margin-left': `${(row._depth - 1) * 24}px` } } // 控制展開(kāi)按鈕的展開(kāi)和關(guān)閉狀態(tài) collapseClass(row: any) { return { 'collapse--open': row.open == false && row.children && row.children.length > 0, 'collapse--close': row.open == true && row.children && row.children.length > 0 } } // 處理展開(kāi)按鈕的點(diǎn)擊事件 handleCollapseClick(row: any) { const _open = row.open; // 通過(guò)節(jié)點(diǎn)訪問(wèn)路徑控制節(jié)點(diǎn)的顯示隱藏,由于內(nèi)存指針的關(guān)系list和tree的節(jié)點(diǎn)操作都會(huì)相互影響 ergodicTree(this.tree, (node: any) => { node._idPath.forEach((pathId: any) => { if (pathId == row.id) { this.$set(node, 'show', !_open); this.$set(node, 'open', !_open) } }) }); row.show = true; row.open = !_open; } } </script> <style lang="scss" scoped> .collapse { display: inline-block; width: 8px; cursor: pointer; margin-right: 8px; } .collapse--open:before { content: '+'; } .collapse--close:before { content: '-'; } </style>
工具方法
考慮數(shù)組轉(zhuǎn)樹(shù)和遍歷樹(shù)都是在實(shí)際項(xiàng)目中都是非常常用的,所以這邊對(duì)這兩個(gè)方法進(jìn)行了封裝。
數(shù)組轉(zhuǎn)樹(shù)結(jié)構(gòu)(./utils/array.ts)
export function arrayToTree(list: object[], props = {id: 'id', pid: 'pid', children: 'children'}) { let tree: object[] = []; let map: any = {}; let listLength = list.length; for (let i = 0; i < listLength; i++) { let node: any = list[i]; let nodeId: any = node[props.id]; map[nodeId] = node; } for (let i = 0; i < listLength; i++) { let node: any = list[i]; let nodePid: any = node[props.pid]; let parentNode: any = map[nodePid]; if (parentNode) { parentNode[props.children] = parentNode[props.children] || []; parentNode[props.children].push(node) } else { tree.push(node) } } return tree }
遍歷樹(shù)結(jié)構(gòu)(./utils/tree.ts)
結(jié)合實(shí)際項(xiàng)目應(yīng)用,我們采用了先序遍歷法對(duì)樹(shù)進(jìn)行遍歷,為了方便在業(yè)務(wù)代碼里的應(yīng)用,在遍歷過(guò)程中會(huì)對(duì)每個(gè)節(jié)點(diǎn)掛載節(jié)點(diǎn)訪問(wèn)路徑 _idPath 屬性和節(jié)點(diǎn)深度 _depth 屬性。
export function ergodicTree(tree: object[], callback: any = () => {}, props = {id: 'id', pid: 'pid', children: 'children'}) { function _ergodicTree(tree: object[], parentIdPath?: any[], depth: number = 0) { const treeLength = tree.length; for (let i = 0; i < treeLength; i++) { let node: any = tree[i]; const _idPath: any[] = parentIdPath ? [...parentIdPath, node[props.id]] : [node[props.id]]; const _depth: number = depth + 1; node._idPath = _idPath; node._depth = _depth; callback(node); if (node[props.children] && node[props.children] instanceof Array) { _ergodicTree(node[props.children], _idPath, _depth) } } } _ergodicTree(tree); return tree; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue+Element UI+Lumen實(shí)現(xiàn)通用表格分頁(yè)功能
- element ui table(表格)實(shí)現(xiàn)點(diǎn)擊一行展開(kāi)功能
- VUE2.0+ElementUI2.0表格el-table實(shí)現(xiàn)表頭擴(kuò)展el-tooltip
- VUE2.0+ElementUI2.0表格el-table循環(huán)動(dòng)態(tài)列渲染的寫(xiě)法詳解
- VUE2.0 ElementUI2.0表格el-table自適應(yīng)高度的實(shí)現(xiàn)方法
- vue+element-ui實(shí)現(xiàn)表格編輯的三種實(shí)現(xiàn)方式
- element-ui 表格數(shù)據(jù)時(shí)間格式化的方法
- element-ui表格數(shù)據(jù)轉(zhuǎn)換的示例代碼
- Vue+element-ui 實(shí)現(xiàn)表格的分頁(yè)功能示例
- vue中element-ui表格縮略圖懸浮放大功能的實(shí)例代碼
相關(guān)文章
vue使用v-for循環(huán)獲取數(shù)組最后一項(xiàng)
這篇文章主要介紹了vue使用v-for循環(huán)獲取數(shù)組最后一項(xiàng)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Grid拖拽布局
這篇文章主要為大家詳細(xì)介紹了如何利用vue實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Grid拖拽布局,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12詳解vue-admin和后端(flask)分離結(jié)合的例子
本篇文章主要介紹了詳解vue-admin和后端(flask)分離結(jié)合的例子,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02nginx部署多個(gè)vue項(xiàng)目的方法示例
這篇文章主要介紹了nginx部署多個(gè)vue項(xiàng)目的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09