JAVA里点击树与表格结合,轻松实现可扩展的树形表格

本文档介绍了一位开发者如何在ElementUI没有树形表格组件的情况下,自行开发一个适用于新手学习的树形表格。作者从一组一维数组开始,通过`arrayToTree`和`ergodicTree`两个工具方法将其转换为树结构,并实现了节点的展开与关闭、视觉层级效果等功能。此外,还提供了源代码和后续优化计划。
摘要由CSDN通过智能技术生成

由于ElementUI目前还未开发树形表格组件,也参阅了网络上部分基于ElementUI表格封装的开源树形组件,都没有找的太理想可进行二次开发的开源项目,所以就萌生了自行开发树形表格。

本示例提供开发思路,移除了多余的样式,比较适合新手入门学习,如果应用于实际项目还请自行封装。

目前还仅仅实现了视觉的树结构的层级效果和控制结构的显示隐藏,后续还会进行不断的完善和优化,有必要的话会对组件进行二次封装,有点在重复造论的感觉哈。

效果图

1460000018829932

完整代码

页面(tree-table.vue)

TreeTable

:class="collapseClass(scope.row)"

:style="tableRowPaddingStyle(scope.row)"

@click="handleCollapseClick(scope.row)">

{{ scope.row.id }}

import {Component, Vue} from 'vue-property-decorator'

// 引入两个封装好的工具方法

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() {

// 准备一组含有父子级关系的一维数组方便示例测试

// 在实际项目应用中,理应通过后端接口返回

let _list = [

{

id: 'a',

pid: '',

name: '部门a',

children: []

},

{

id: 'a1',

pid: 'a',

name: '子部门a1',

children: []

},

{

id: 'a2',

pid: 'a',

name: '子部门a2',

children: []

},

{

id: 'a2-1',

pid: 'a2',

name: '子部门a2-1',

children: []

},

{

id: 'a2-2',

pid: 'a2',

name: '子部门a2-2',

children: []

},

{

id: 'a3',

pid: 'a',

name: '子部门a3',

children: []

},

{

id: 'a3-1',

pid: 'a3',

name: '子部门a3-1',

children: []

},

{

id: 'b',

pid: '',

name: '部门b',

children: []

},

{

id: 'b1',

pid: 'b',

name: '子部门b1',

children: []

},

{

id: 'c',

pid: '',

name: '部门c',

children: []

},

];

// 将一维数组转成树形结构并存储于tree变量

this.tree = arrayToTree(_list);

// 考虑到实际应用过程中接口返回的数据是无序的,所以我们对tree进行先序遍历将节点一一插入到list变量

this.list = [];

ergodicTree(this.tree, (node: any) => {

this.list.push(node);

// 遍历过程中并对每个节点挂载open和show属性

// open:控制节点的打开和关闭

// show:控制节点的显示和隐藏

this.$set(node, 'open', true);

this.$set(node, 'show', true)

})

}

// 控制行的显示和隐藏

tableRowStyle(scope: any) {

return {

'display': scope.row.show ? '' : 'none'

}

}

// 通过每个节点的深度,设置行的缩进实现视觉上的层级效果

tableRowPaddingStyle(row: any) {

return {

'margin-left': `${(row._depth - 1) * 24}px`

}

}

// 控制展开按钮的展开和关闭状态

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

}

}

// 处理展开按钮的点击事件

handleCollapseClick(row: any) {

const _open = row.open;

// 通过节点访问路径控制节点的显示隐藏,由于内存指针的关系list和tree的节点操作都会相互影响

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;

}

}

.collapse {

display: inline-block;

width: 8px;

cursor: pointer;

margin-right: 8px;

}

.collapse--open:before {

content: '+';

}

.collapse--close:before {

content: '-';

}

工具方法

考虑数组转树和遍历树都是在实际项目中都是非常常用的,所以这边对这两个方法进行了封装。

数组转树结构(./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

}

遍历树结构(./utils/tree.ts)

结合实际项目应用,我们采用了先序遍历法对树进行遍历,为了方便在业务代码里的应用,在遍历过程中会对每个节点挂载节点访问路径 _idPath 属性和节点深度 _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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值