tree-grid-component
Version:
199 lines (173 loc) • 7.24 kB
Markdown
> 由于公司产品(基于vue2.0)需要,要实现一个[树形表格](https://github.com/Inception-entry/vue-tree-grid)的功能,百度、google找了一通,并没有发现很靠谱的,也不是很灵活。所以就用vue自己写了一个,还望大家多多指教。
- 根路由:拓展的内部表格数据过多, 是时间分片方式处理的
- /virtual: 拓展的内部表格数据过多, 是虚拟列表方式处理的(强烈建议用此方式)
- 效果图([Demo](https://inception-entry.github.io/dist/#/))
- 主要代码
> index.vue页面实现业务逻辑代码,比如树表格上面的一些操作按钮的实现及数据获取。
>
``` html
<template>
<div class="common-css contains">
<tree-grid
ref="recTree"
:list.sync="treeDataSource"
@handlerFold="handlerFold"
@handlerExpand="handlerExpand"
:treeColumnList="treeColumns"
:columnList="tableColumns"
:tableListName="childrenAlias">
</tree-grid>
</div>
</template>
<script>
import dataJson from './data1.json';
import treeGrid from '@/components/tree-grid.vue';
export default {
data() {
return {
treeDataSource: dataJson,
treeColumns: [], // 树表头
tableColumns: [],// 内部表格表头
childrenAlias: 'sub_account_list',
treeDataSource: [] // 组合成树表格接收的数据
}
},
components: {
treeGrid
},
methods: {
handlerFold(val) {
console.log('展开/折叠')
},
handlerExpand(val) {
console.log('扩展/收起');
},
}
}
</script>
```
``` bash
原始数据`list`:是不包含子数据的数据结构,即没有层级结构,通过parentId来获取对应父子层级结构,例如:
[{id:111,parentId:0,name:'父级'},{id:111,parentId:111,name:'子级'}...]
`treeDataSource`:是树表格需要的数据结构,例如:
[{id:0,name:'父级',children:[{id:10,name:'子级',children:[]}]},...]
```
> 如果后台返回给你的是原始数据格式,就可以用下面方法封装成树表格可以使用的数据结构:
``` bash
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-grid.vue页面。此页面是实现树表格的关健页面。主要代码如下:
``` html
<template>
<div class="tree-grid">
<div class="tree-head">
<table>
<tr>
<th
:class="`th${index + 1}`"
:style="treeHeaderRender(item, index, treeColumnList)"
v-for="(item, index) in treeColumnList"
:key="item.key">
{{ item.name }}
</th>
</tr>
</table>
</div>
<div id="scrollWrap" class="tree-wrap">
<div class="tree-body">
<table v-if="treeDataSource.length > 0">
<tbody>
<tr>
<td>
<tree-unit
v-for="(model, i) in treeDataSource"
:key="'root_node_' + i"
:root="0"
:num="i"
@handlerFold="handlerFold"
@handlerExpand="handlerExpand"
:nodes="treeDataSource.length"
:trees.sync="treeDataSource"
:model="model"
:treeColumnList="treeColumnList"
:columnList="columnList"
:tableListName="tableListName">
</tree-unit>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
```
| 属性 | 说明 | 类型 | 参数 | 默认值 |
| ---- | ---- | ---- | ---- | ---- |
| list | 树表格需要的数据结构 | Array | - | [] |
| treeColumnList | 树表格的最外层表头 | Array | - | [] |
| columnList | 内部表格表头(具体见下文:Columns Configs) | Array | - | [] |
| tableListName | 树表格结构中内部表格的属性名 | String | - | '' |
| 属性 | 说明 | 类型 | 默认值 |
| ---- | ---- | ---- | ---- |
| key | 列唯一标识 | Number | 无 |
| name | 列标题名称 | String | '' |
| fieldName | 对应列内容的属性名 | String | '' |
| minWidth | 列最小宽度 | Number | 无 |
| maxWidth | 列最大宽度 | Number | 无 |
| expandFunc | 是否有拓展功能 | Boolean | false |
| mainAccountSlotName | 列类型为复杂结构时,对应的主账号插槽名称 | String | '' |
| slotName | 列类型为 'template'(自定义列模板) 时,对应的插槽名称(它可以获取到 row)[作用域插槽] | Object | {} |
| 事件名 | 说明 | 参数 |
| ---- | ---- | ---- |
| handlerFold | 鼠标单击树形icon | row |
| handlerExpand | 鼠标单击展开单元格 | row |
> 补充一点:不要只看js部分,css部分才是这个树表格的关健所在。当然里面我采用了大量的计算属性去判断各种样式的展示,还有一种方法,就是在`initTreeData`方法里面去实现,这个方法就是处理或添加一些我们树表格所使用的信息。比如我现在在里面实现的层级线的偏移量`m.bLeft = level === 1 ? 65 : (level - 2) * 14 + 65` 这个计算如果没有看明白,可以留言。
- 最后,如有问题,还请多多包含,多多指教!!!顺便给我好久没有更新的博客打个广告,
欢迎点击([<span style="color:#f24c27;font-weight:600">sanks的博客</span>](https://www.sanks-blog.com/))
- 源码地址[github](https://github.com/Inception-entry/vue-tree-grid),欢迎star。
- 参考资源[隔壁家的老黄](https://www.cnblogs.com/ychl/p/6075106.html)
- 参考资源[城池](https://juejin.cn/post/6844903645624926215)
``` bash
npm install
npm run dev
npm run build
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).