超大量数据,前端树形结构展示

火影  金牌会员 | 2024-6-18 17:54:14 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 545|帖子 545|积分 1635

后端返回了50万数据,让前端一次性展示成树,之前用的ant-design-vue的tree插件,卡的死死的,颠末大量实验,现发现三种树可以支持如此大数量的数据。

目次
第一种:vue-easy-tree
使用方式:
1.安装插件
2.引入插件
全局引入
组件引入
3.使用
 在使用虚拟滚动时,必须设置 node-key。
4.api(githup经常打不开,哎,复制了一下各人一起看)
基础用法
可选择
懒加载自界说叶子节点
默认展开和默认选中
禁用状态
树节点的选择
自界说节点内容
节点过滤
手风琴模式
可拖拽节点
Attributes
props
方法
Events
Scoped Slot
第二种:zTree(vue-giant-tree)延迟加载
1.安装插件
2.页面使用
第三种:vxe-table-plugin-virtual-tree
总结




第一种:vue-easy-tree



  • 大数据量支持虚拟滚动
  • 基本树形数据的展示
  • 支持checkbox选择
  • 支持懒加载
  • 默认展开和默认选中
  • 禁用节点
  • 通过多种方式选中节点和获取选中的节点信息
  • 支持自界说节点内容
  • 支持节点过滤
  • 非虚拟滚动下,支持手风琴模式
  • 非懒加载时,支持节点拖拽
githup上有具体api介绍
https://github.com/wchbrad/vue-easy-tree/blob/aa225219e4dc9e88f0a633405fe3947991dfd224/element-ui-tree.zh-CN.md
使用方式:

1.安装插件

  1. npm install @wchbrad/vue-easy-tree
复制代码
2.引入插件

全局引入

在 main.js 文件中引入:
  1. import Vue from "vue";
  2. import VueEasyTree from "@wchbrad/vue-easy-tree";
  3. // 样式文件,可以根据需要自定义样式或主题
  4. import "@wchbrad/vue-easy-tree/src/assets/index.scss"
  5. Vue.use(VueEasyTree)
复制代码
组件引入

在组件中引入:
  1. import VueEasyTree from "@wchbrad/vue-easy-tree";
  2. // 样式文件,可以根据需要自定义样式或主题
  3. import "@wchbrad/vue-easy-tree/src/assets/index.scss"
  4. export default {
  5.   components: {
  6.     VueEasyTree
  7.   }
  8. }
复制代码
3.使用

 在使用虚拟滚动时,必须设置 node-key。


4.api(githup经常打不开,哎,复制了一下各人一起看)


基础用法

基础的树形结构展示。
  1. <vue-easy-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></vue-easy-tree>
  2. <script>
  3.   export default {
  4.     data() {
  5.       return {
  6.         data: [{
  7.           label: '一级 1',
  8.           children: [{
  9.             label: '二级 1-1',
  10.             children: [{
  11.               label: '三级 1-1-1'
  12.             }]
  13.           }]
  14.         }, {
  15.           label: '一级 2',
  16.           children: [{
  17.             label: '二级 2-1',
  18.             children: [{
  19.               label: '三级 2-1-1'
  20.             }]
  21.           }, {
  22.             label: '二级 2-2',
  23.             children: [{
  24.               label: '三级 2-2-1'
  25.             }]
  26.           }]
  27.         }, {
  28.           label: '一级 3',
  29.           children: [{
  30.             label: '二级 3-1',
  31.             children: [{
  32.               label: '三级 3-1-1'
  33.             }]
  34.           }, {
  35.             label: '二级 3-2',
  36.             children: [{
  37.               label: '三级 3-2-1'
  38.             }]
  39.           }]
  40.         }],
  41.         defaultProps: {
  42.           children: 'children',
  43.           label: 'label'
  44.         }
  45.       };
  46.     },
  47.     methods: {
  48.       handleNodeClick(data) {
  49.         console.log(data);
  50.       }
  51.     }
  52.   };
  53. </script>
复制代码
可选择

实用于需要选择层级时使用。
本例还展示了动态加载节点数据的方法。
  1. <vue-easy-tree
  2.   :props="props"
  3.   :load="loadNode"
  4.   lazy
  5.   show-checkbox
  6.   @check-change="handleCheckChange">
  7. </vue-easy-tree>
  8. <script>
  9.   export default {
  10.     data() {
  11.       return {
  12.         props: {
  13.           label: 'name',
  14.           children: 'zones'
  15.         },
  16.         count: 1
  17.       };
  18.     },
  19.     methods: {
  20.       handleCheckChange(data, checked, indeterminate) {
  21.         console.log(data, checked, indeterminate);
  22.       },
  23.       handleNodeClick(data) {
  24.         console.log(data);
  25.       },
  26.       loadNode(node, resolve) {
  27.         if (node.level === 0) {
  28.           return resolve([{ name: 'region1' }, { name: 'region2' }]);
  29.         }
  30.         if (node.level > 3) return resolve([]);
  31.         var hasChild;
  32.         if (node.data.name === 'region1') {
  33.           hasChild = true;
  34.         } else if (node.data.name === 'region2') {
  35.           hasChild = false;
  36.         } else {
  37.           hasChild = Math.random() > 0.5;
  38.         }
  39.         setTimeout(() => {
  40.           var data;
  41.           if (hasChild) {
  42.             data = [{
  43.               name: 'zone' + this.count++
  44.             }, {
  45.               name: 'zone' + this.count++
  46.             }];
  47.           } else {
  48.             data = [];
  49.           }
  50.           resolve(data);
  51.         }, 500);
  52.       }
  53.     }
  54.   };
  55. </script>
复制代码
懒加载自界说叶子节点

由于在点击节点时才进行该层数据的获取,默认情况下 Tree 无法预知某个节点是否为叶子节点,所以会为每个节点添加一个下拉按钮,假如节点没有下层数据,则点击后下拉按钮会消失。同时,你也可以提前告知 Tree 某个节点是否为叶子节点,从而避免在叶子节点前渲染下拉按钮。
  1. <vue-easy-tree
  2.   :props="props"
  3.   :load="loadNode"
  4.   lazy
  5.   show-checkbox>
  6. </vue-easy-tree>
  7. <script>
  8.   export default {
  9.     data() {
  10.       return {
  11.         props: {
  12.           label: 'name',
  13.           children: 'zones',
  14.           isLeaf: 'leaf'
  15.         },
  16.       };
  17.     },
  18.     methods: {
  19.       loadNode(node, resolve) {
  20.         if (node.level === 0) {
  21.           return resolve([{ name: 'region' }]);
  22.         }
  23.         if (node.level > 1) return resolve([]);
  24.         setTimeout(() => {
  25.           const data = [{
  26.             name: 'leaf',
  27.             leaf: true
  28.           }, {
  29.             name: 'zone'
  30.           }];
  31.           resolve(data);
  32.         }, 500);
  33.       }
  34.     }
  35.   };
  36. </script>
复制代码
默认展开和默认选中

可将 Tree 的某些节点设置为默认展开或默认选中
分别通过default-expanded-keys和default-checked-keys设置默认展开和默认选中的节点。需要注意的是,此时必须设置node-key,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的。
  1. <vue-easy-tree
  2.   :data="data"
  3.   show-checkbox
  4.   node-key="id"
  5.   :default-expanded-keys="[2, 3]"
  6.   :default-checked-keys="[5]"
  7.   :props="defaultProps">
  8. </vue-easy-tree>
  9. <script>
  10.   export default {
  11.     data() {
  12.       return {
  13.         data: [{
  14.           id: 1,
  15.           label: '一级 1',
  16.           children: [{
  17.             id: 4,
  18.             label: '二级 1-1',
  19.             children: [{
  20.               id: 9,
  21.               label: '三级 1-1-1'
  22.             }, {
  23.               id: 10,
  24.               label: '三级 1-1-2'
  25.             }]
  26.           }]
  27.         }, {
  28.           id: 2,
  29.           label: '一级 2',
  30.           children: [{
  31.             id: 5,
  32.             label: '二级 2-1'
  33.           }, {
  34.             id: 6,
  35.             label: '二级 2-2'
  36.           }]
  37.         }, {
  38.           id: 3,
  39.           label: '一级 3',
  40.           children: [{
  41.             id: 7,
  42.             label: '二级 3-1'
  43.           }, {
  44.             id: 8,
  45.             label: '二级 3-2'
  46.           }]
  47.         }],
  48.         defaultProps: {
  49.           children: 'children',
  50.           label: 'label'
  51.         }
  52.       };
  53.     }
  54.   };
  55. </script>
复制代码
禁用状态

可将 Tree 的某些节点设置为禁用状态
通过disabled设置禁用状态。
  1. <vue-easy-tree
  2.   :data="data"
  3.   show-checkbox
  4.   node-key="id"
  5.   :default-expanded-keys="[2, 3]"
  6.   :default-checked-keys="[5]">
  7. </vue-easy-tree>
  8. <script>
  9.   export default {
  10.     data() {
  11.       return {
  12.         data: [{
  13.           id: 1,
  14.           label: '一级 2',
  15.           children: [{
  16.             id: 3,
  17.             label: '二级 2-1',
  18.             children: [{
  19.               id: 4,
  20.               label: '三级 3-1-1'
  21.             }, {
  22.               id: 5,
  23.               label: '三级 3-1-2',
  24.               disabled: true
  25.             }]
  26.           }, {
  27.             id: 2,
  28.             label: '二级 2-2',
  29.             disabled: true,
  30.             children: [{
  31.               id: 6,
  32.               label: '三级 3-2-1'
  33.             }, {
  34.               id: 7,
  35.               label: '三级 3-2-2',
  36.               disabled: true
  37.             }]
  38.           }]
  39.         }],
  40.         defaultProps: {
  41.           children: 'children',
  42.           label: 'label'
  43.         }
  44.       };
  45.     }
  46.   };
  47. </script>
复制代码
树节点的选择

本例展示如何获取和设置选中节点。获取和设置各有两种方式:通过 node 或通过 key。假如需要通过 key 来获取或设置,则必须设置node-key。
  1. <vue-easy-tree
  2.   :data="data"
  3.   show-checkbox
  4.   default-expand-all
  5.   node-key="id"
  6.   ref="tree"
  7.   highlight-current
  8.   :props="defaultProps">
  9. </vue-easy-tree>
  10. <div class="buttons">
  11.   <el-button @click="getCheckedNodes">通过 node 获取</el-button>
  12.   <el-button @click="getCheckedKeys">通过 key 获取</el-button>
  13.   <el-button @click="setCheckedNodes">通过 node 设置</el-button>
  14.   <el-button @click="setCheckedKeys">通过 key 设置</el-button>
  15.   <el-button @click="resetChecked">清空</el-button>
  16. </div>
  17. <script>
  18.   export default {
  19.     methods: {
  20.       getCheckedNodes() {
  21.         console.log(this.$refs.tree.getCheckedNodes());
  22.       },
  23.       getCheckedKeys() {
  24.         console.log(this.$refs.tree.getCheckedKeys());
  25.       },
  26.       setCheckedNodes() {
  27.         this.$refs.tree.setCheckedNodes([{
  28.           id: 5,
  29.           label: '二级 2-1'
  30.         }, {
  31.           id: 9,
  32.           label: '三级 1-1-1'
  33.         }]);
  34.       },
  35.       setCheckedKeys() {
  36.         this.$refs.tree.setCheckedKeys([3]);
  37.       },
  38.       resetChecked() {
  39.         this.$refs.tree.setCheckedKeys([]);
  40.       }
  41.     },
  42.     data() {
  43.       return {
  44.         data: [{
  45.           id: 1,
  46.           label: '一级 1',
  47.           children: [{
  48.             id: 4,
  49.             label: '二级 1-1',
  50.             children: [{
  51.               id: 9,
  52.               label: '三级 1-1-1'
  53.             }, {
  54.               id: 10,
  55.               label: '三级 1-1-2'
  56.             }]
  57.           }]
  58.         }, {
  59.           id: 2,
  60.           label: '一级 2',
  61.           children: [{
  62.             id: 5,
  63.             label: '二级 2-1'
  64.           }, {
  65.             id: 6,
  66.             label: '二级 2-2'
  67.           }]
  68.         }, {
  69.           id: 3,
  70.           label: '一级 3',
  71.           children: [{
  72.             id: 7,
  73.             label: '二级 3-1'
  74.           }, {
  75.             id: 8,
  76.             label: '二级 3-2'
  77.           }]
  78.         }],
  79.         defaultProps: {
  80.           children: 'children',
  81.           label: 'label'
  82.         }
  83.       };
  84.     }
  85.   };
  86. </script>
复制代码
自界说节点内容

节点的内容支持自界说,可以在节点区添加按钮或图标等内容
可以通过两种方法进行树节点内容的自界说:render-content和 scoped slot。使用render-content指定渲染函数,该函数返回需要的节点区内容即可。渲染函数的用法请参考 Vue 文档。使用 scoped slot 会传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据。注意:由于 jsfiddle 不支持 JSX 语法,所以render-content示例在 jsfiddle 中无法运行。但是在实际的项目中,只要精确地设置了相关依赖,就可以正常运行。
  1. <div class="custom-tree-container">
  2.   <div class="block">
  3.     <p>使用 render-content</p>
  4.     <vue-easy-tree
  5.       :data="data"
  6.       show-checkbox
  7.       node-key="id"
  8.       default-expand-all
  9.       :expand-on-click-node="false"
  10.       :render-content="renderContent">
  11.     </vue-easy-tree>
  12.   </div>
  13.   <div class="block">
  14.     <p>使用 scoped slot</p>
  15.     <vue-easy-tree
  16.       :data="data"
  17.       show-checkbox
  18.       node-key="id"
  19.       default-expand-all
  20.       :expand-on-click-node="false">
  21.       <span class="custom-tree-node" slot-scope="{ node, data }">
  22.         <span>{{ node.label }}</span>
  23.         <span>
  24.           <el-button
  25.             type="text"
  26.             size="mini"
  27.             @click="() => append(data)">
  28.             Append
  29.           </el-button>
  30.           <el-button
  31.             type="text"
  32.             size="mini"
  33.             @click="() => remove(node, data)">
  34.             Delete
  35.           </el-button>
  36.         </span>
  37.       </span>
  38.     </vue-easy-tree>
  39.   </div>
  40. </div>
  41. <script>
  42.   let id = 1000;
  43.   export default {
  44.     data() {
  45.       const data = [{
  46.         id: 1,
  47.         label: '一级 1',
  48.         children: [{
  49.           id: 4,
  50.           label: '二级 1-1',
  51.           children: [{
  52.             id: 9,
  53.             label: '三级 1-1-1'
  54.           }, {
  55.             id: 10,
  56.             label: '三级 1-1-2'
  57.           }]
  58.         }]
  59.       }, {
  60.         id: 2,
  61.         label: '一级 2',
  62.         children: [{
  63.           id: 5,
  64.           label: '二级 2-1'
  65.         }, {
  66.           id: 6,
  67.           label: '二级 2-2'
  68.         }]
  69.       }, {
  70.         id: 3,
  71.         label: '一级 3',
  72.         children: [{
  73.           id: 7,
  74.           label: '二级 3-1'
  75.         }, {
  76.           id: 8,
  77.           label: '二级 3-2'
  78.         }]
  79.       }];
  80.       return {
  81.         data: JSON.parse(JSON.stringify(data)),
  82.         data: JSON.parse(JSON.stringify(data))
  83.       }
  84.     },
  85.     methods: {
  86.       append(data) {
  87.         const newChild = { id: id++, label: 'testtest', children: [] };
  88.         if (!data.children) {
  89.           this.$set(data, 'children', []);
  90.         }
  91.         data.children.push(newChild);
  92.       },
  93.       remove(node, data) {
  94.         const parent = node.parent;
  95.         const children = parent.data.children || parent.data;
  96.         const index = children.findIndex(d => d.id === data.id);
  97.         children.splice(index, 1);
  98.       },
  99.       renderContent(h, { node, data, store }) {
  100.         return (
  101.           <span class="custom-tree-node">
  102.             <span>{node.label}</span>
  103.             <span>
  104.               <el-button size="mini" type="text" on-click={ () => this.append(data) }>Append</el-button>
  105.               <el-button size="mini" type="text" on-click={ () => this.remove(node, data) }>Delete</el-button>
  106.             </span>
  107.           </span>);
  108.       }
  109.     }
  110.   };
  111. </script>
  112. <style>
  113.   .custom-tree-node {
  114.     flex: 1;
  115.     display: flex;
  116.     align-items: center;
  117.     justify-content: space-between;
  118.     font-size: 14px;
  119.     padding-right: 8px;
  120.   }
  121. </style>
复制代码
节点过滤

通过关键字过滤树节点
在需要对节点进行过滤时,调用 Tree 实例的filter方法,参数为关键字。需要注意的是,此时需要设置filter-node-method,值为过滤函数。
  1. <el-input
  2.   placeholder="输入关键字进行过滤"
  3.   v-model="filterText">
  4. </el-input>
  5. <vue-easy-tree
  6.   class="filter-tree"
  7.   :data="data"
  8.   :props="defaultProps"
  9.   default-expand-all
  10.   :filter-node-method="filterNode"
  11.   ref="tree">
  12. </vue-easy-tree>
  13. <script>
  14.   export default {
  15.     watch: {
  16.       filterText(val) {
  17.         this.$refs.tree.filter(val);
  18.       }
  19.     },
  20.     methods: {
  21.       filterNode(value, data) {
  22.         if (!value) return true;
  23.         return data.label.indexOf(value) !== -1;
  24.       }
  25.     },
  26.     data() {
  27.       return {
  28.         filterText: '',
  29.         data: [{
  30.           id: 1,
  31.           label: '一级 1',
  32.           children: [{
  33.             id: 4,
  34.             label: '二级 1-1',
  35.             children: [{
  36.               id: 9,
  37.               label: '三级 1-1-1'
  38.             }, {
  39.               id: 10,
  40.               label: '三级 1-1-2'
  41.             }]
  42.           }]
  43.         }, {
  44.           id: 2,
  45.           label: '一级 2',
  46.           children: [{
  47.             id: 5,
  48.             label: '二级 2-1'
  49.           }, {
  50.             id: 6,
  51.             label: '二级 2-2'
  52.           }]
  53.         }, {
  54.           id: 3,
  55.           label: '一级 3',
  56.           children: [{
  57.             id: 7,
  58.             label: '二级 3-1'
  59.           }, {
  60.             id: 8,
  61.             label: '二级 3-2'
  62.           }]
  63.         }],
  64.         defaultProps: {
  65.           children: 'children',
  66.           label: 'label'
  67.         }
  68.       };
  69.     }
  70.   };
  71. </script>
复制代码
手风琴模式

对于同一级的节点,每次只能展开一个
  1. <vue-easy-tree
  2.   :data="data"
  3.   :props="defaultProps"
  4.   accordion
  5.   @node-click="handleNodeClick">
  6. </vue-easy-tree>
  7. <script>
  8.   export default {
  9.     data() {
  10.       return {
  11.         data: [{
  12.           label: '一级 1',
  13.           children: [{
  14.             label: '二级 1-1',
  15.             children: [{
  16.               label: '三级 1-1-1'
  17.             }]
  18.           }]
  19.         }, {
  20.           label: '一级 2',
  21.           children: [{
  22.             label: '二级 2-1',
  23.             children: [{
  24.               label: '三级 2-1-1'
  25.             }]
  26.           }, {
  27.             label: '二级 2-2',
  28.             children: [{
  29.               label: '三级 2-2-1'
  30.             }]
  31.           }]
  32.         }, {
  33.           label: '一级 3',
  34.           children: [{
  35.             label: '二级 3-1',
  36.             children: [{
  37.               label: '三级 3-1-1'
  38.             }]
  39.           }, {
  40.             label: '二级 3-2',
  41.             children: [{
  42.               label: '三级 3-2-1'
  43.             }]
  44.           }]
  45.         }],
  46.         defaultProps: {
  47.           children: 'children',
  48.           label: 'label'
  49.         }
  50.       };
  51.     },
  52.     methods: {
  53.       handleNodeClick(data) {
  54.         console.log(data);
  55.       }
  56.     }
  57.   };
  58. </script>
复制代码
可拖拽节点

通过 draggable 属性可让节点变为可拖拽。
  1. <vue-easy-tree
  2.   :data="data"
  3.   node-key="id"
  4.   default-expand-all
  5.   @node-drag-start="handleDragStart"
  6.   @node-drag-enter="handleDragEnter"
  7.   @node-drag-leave="handleDragLeave"
  8.   @node-drag-over="handleDragOver"
  9.   @node-drag-end="handleDragEnd"
  10.   @node-drop="handleDrop"
  11.   draggable
  12.   :allow-drop="allowDrop"
  13.   :allow-drag="allowDrag">
  14. </vue-easy-tree>
  15. <script>
  16.   export default {
  17.     data() {
  18.       return {
  19.         data: [{
  20.           id: 1,
  21.           label: '一级 1',
  22.           children: [{
  23.             id: 4,
  24.             label: '二级 1-1',
  25.             children: [{
  26.               id: 9,
  27.               label: '三级 1-1-1'
  28.             }, {
  29.               id: 10,
  30.               label: '三级 1-1-2'
  31.             }]
  32.           }]
  33.         }, {
  34.           id: 2,
  35.           label: '一级 2',
  36.           children: [{
  37.             id: 5,
  38.             label: '二级 2-1'
  39.           }, {
  40.             id: 6,
  41.             label: '二级 2-2'
  42.           }]
  43.         }, {
  44.           id: 3,
  45.           label: '一级 3',
  46.           children: [{
  47.             id: 7,
  48.             label: '二级 3-1'
  49.           }, {
  50.             id: 8,
  51.             label: '二级 3-2',
  52.             children: [{
  53.              id: 11,
  54.               label: '三级 3-2-1'
  55.             }, {
  56.               id: 12,
  57.               label: '三级 3-2-2'
  58.             }, {
  59.               id: 13,
  60.               label: '三级 3-2-3'
  61.             }]
  62.           }]
  63.         }],
  64.         defaultProps: {
  65.           children: 'children',
  66.           label: 'label'
  67.         }
  68.       };
  69.     },
  70.     methods: {
  71.       handleDragStart(node, ev) {
  72.         console.log('drag start', node);
  73.       },
  74.       handleDragEnter(draggingNode, dropNode, ev) {
  75.         console.log('tree drag enter: ', dropNode.label);
  76.       },
  77.       handleDragLeave(draggingNode, dropNode, ev) {
  78.         console.log('tree drag leave: ', dropNode.label);
  79.       },
  80.       handleDragOver(draggingNode, dropNode, ev) {
  81.         console.log('tree drag over: ', dropNode.label);
  82.       },
  83.       handleDragEnd(draggingNode, dropNode, dropType, ev) {
  84.         console.log('tree drag end: ', dropNode && dropNode.label, dropType);
  85.       },
  86.       handleDrop(draggingNode, dropNode, dropType, ev) {
  87.         console.log('tree drop: ', dropNode.label, dropType);
  88.       },
  89.       allowDrop(draggingNode, dropNode, type) {
  90.         if (dropNode.data.label === '二级 3-1') {
  91.           return type !== 'inner';
  92.         } else {
  93.           return true;
  94.         }
  95.       },
  96.       allowDrag(draggingNode) {
  97.         return draggingNode.data.label.indexOf('三级 3-2-2') === -1;
  98.       }
  99.     }
  100.   };
  101. </script>
复制代码
Attributes

参数阐明类型可选值默认值data展示数据array——empty-text内容为空的时候展示的文本String——node-key每个树节点用来作为唯一标识的属性,整棵树应该是唯一的String——props设置选项,具体看下表object——render-after-expand是否在第一次展开某个树节点后才渲染其子节点boolean—trueload加载子树数据的方法,仅当 lazy 属性为true 时生效function(node, resolve)——render-content树节点的内容区的渲染 FunctionFunction(h, { node, data, store }——highlight-current是否高亮当前选中节点,默认值是 false。boolean—falsedefault-expand-all是否默认展开全部节点boolean—falseexpand-on-click-node是否在点击节点的时候展开大概收缩节点, 默认值为 true,假如为 false,则只有点箭头图标的时候才会展开大概收缩节点。boolean—truecheck-on-click-node是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。boolean—falseauto-expand-parent展开子节点的时候是否自动展开父节点boolean—truedefault-expanded-keys默认展开的节点的 key 的数组array——show-checkbox节点是否可被选择boolean—falsecheck-strictly在显示复选框的情况下,是否严格的遵循父子不相互关联的做法,默认为 falseboolean—falsedefault-checked-keys默认勾选的节点的 key 的数组array——current-node-key当前选中的节点string, number——filter-node-method对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐蔽Function(value, data, node)——accordion是否每次只打开一个同级树节点展开boolean—falseindent相邻级节点间的程度缩进,单位为像素number—16item-size每个节点的高度,单位为像素number—26icon-class自界说树节点的图标string--lazy是否懒加载子节点,需与 load 方法联合使用boolean—falsedraggable是否开启拖拽节点功能boolean—falseallow-drag判断节点能否被拖拽Function(node)——allow-drop拖拽时判定目标节点能否被放置。type 参数有三种情况:'prev'、'inner' 和 'next',分别表示放置在目标节点前、插入至目标节点和放置在目标节点后Function(draggingNode, dropNode, type)—— props

参数阐明类型可选值默认值label指定节点标签为节点对象的某个属性值string, function(data, node)——children指定子树为节点对象的某个属性值string——disabled指定节点选择框是否禁用为节点对象的某个属性值boolean, function(data, node)——isLeaf指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效boolean, function(data, node)—— 方法

Tree 内部使用了 Node 类型的对象来包装用户传入的数据,用来保存目前节点的状态。 Tree 拥有如下方法:
方法名阐明参数filter对树节点进行筛选操作吸取一个恣意类型的参数,该参数会在 filter-node-method 中作为第一个参数updateKeyChildren通过 keys 设置节点子元素,使用此方法必须设置 node-key 属性(key, data) 吸取两个参数,1. 节点 key 2. 节点数据的数组getCheckedNodes若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点所构成的数组(leafOnly, includeHalfChecked) 吸取两个 boolean 类型的参数,1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 falsesetCheckedNodes设置目前勾选的节点,使用此方法必须设置 node-key 属性(nodes) 吸取勾选节点数据的数组getCheckedKeys若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所构成的数组(leafOnly) 吸取一个 boolean 类型的参数,若为 true 则仅返回被选中的叶子节点的 keys,默认值为 falsesetCheckedKeys通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性(keys, leafOnly) 吸取两个参数,1. 勾选节点的 key 的数组 2. boolean 类型的参数,若为 true 则仅设置叶子节点的选中状态,默认值为 falsesetCheckedAll虚拟滚动时,快速全选大概扫除全选的方法,使用setCheckedKeys可能会卡顿(checked) 吸取一个 boolean 类型的参数,若为 true 则全选全部节点,若为 false 则取消全部节点的选中/半选状态,默认值为 falsesetChecked通过 key / data 设置某个节点的勾选状态,使用此方法必须设置 node-key 属性(key/data, checked, deep) 吸取三个参数,1. 勾选节点的 key 大概 data 2. boolean 类型,节点是否选中 3. boolean 类型,是否设置子节点 ,默认为 falsegetHalfCheckedNodes若节点可被选择(即 show-checkbox 为 true),则返回目前半选中的节点所构成的数组-getHalfCheckedKeys若节点可被选择(即 show-checkbox 为 true),则返回目前半选中的节点的 key 所构成的数组-getCurrentKey获取当前被选中节点的 key,使用此方法必须设置 node-key 属性,若没有节点被选中则返回 null—getCurrentNode获取当前被选中节点的 data,若没有节点被选中则返回 null—setCurrentKey通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性(key) 待被选节点的 key,若为 null 则取消当前高亮的节点setCurrentNode通过 node 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性(node) 待被选节点的 nodegetNode根据 data 大概 key 拿到 Tree 组件中的 node(data) 要获得 node 的 key 大概 dataremove删除 Tree 中的一个节点,使用此方法必须设置 node-key 属性(data) 要删除的节点的 data 大概 nodeappend为 Tree 中的一个节点追加一个子节点(data, parentNode) 吸取两个参数,1. 要追加的子节点的 data 2. 子节点的 parent 的 data、key 大概 nodeinsertBefore为 Tree 的一个节点的前面增加一个节点(data, refNode) 吸取两个参数,1. 要增加的节点的 data 2. 要增加的节点的后一个节点的 data、key 大概 nodeinsertAfter为 Tree 的一个节点的后面增加一个节点(data, refNode) 吸取两个参数,1. 要增加的节点的 data 2. 要增加的节点的前一个节点的 data、key 大概 node Events

事件名称阐明回调参数node-click节点被点击时的回调共三个参数,依次为:通报给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。node-contextmenu当某一节点被鼠标右键点击时会触发该事件共四个参数,依次为:event、通报给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。check-change节点选中状态发生厘革时的回调共三个参数,依次为:通报给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点check当复选框被点击的时候触发共两个参数,依次为:通报给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性current-change当前选中节点厘革时触发的事件共两个参数,依次为:当前节点的数据,当前节点的 Node 对象node-expand节点被展开时触发的事件共三个参数,依次为:通报给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身node-collapse节点被关闭时触发的事件共三个参数,依次为:通报给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身node-drag-start节点开始拖拽时触发的事件共两个参数,依次为:被拖拽节点对应的 Node、eventnode-drag-enter拖拽进入其他节点时触发的事件共三个参数,依次为:被拖拽节点对应的 Node、所进入节点对应的 Node、eventnode-drag-leave拖拽离开某个节点时触发的事件共三个参数,依次为:被拖拽节点对应的 Node、所离开节点对应的 Node、eventnode-drag-over在拖拽节点时触发的事件(雷同欣赏器的 mouseover 事件)共三个参数,依次为:被拖拽节点对应的 Node、当前进入节点对应的 Node、eventnode-drag-end拖拽结束时(可能未成功)触发的事件共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点(可能为空)、被拖拽节点的放置位置(before、after、inner)、eventnode-drop拖拽成功完成时触发的事件共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置(before、after、inner)、event Scoped Slot

name阐明—自界说树节点的内容,参数为 { node, data }
第二种:zTree(vue-giant-tree)延迟加载



巨树:基于ztree封装的 Vue 树形组件,轻松实现海量数据的高性能渲染。
Vue 的数据监听机制决定了在大数据量场景下的渲染性能非常低下,基于 Vue 实现的通例树组件险些无法胜任上万条数据的高性能渲染,在 IE 欣赏器(即便是 IE11)中很容易导致页面卡死甚至欣赏器崩溃。
为了摆脱数据监听,只能放弃通过 Vue 渲染,采用通例 DOM 操作的方式。在这个范畴ztree是当之无愧最成熟的方案,因此 vue-giant-tree 直接基于 ztree 做上层封装,以组件的情势将 ztree 的设置和事件袒露出来,使其可以方便的在 Vue 项目中安装使用。
vue-giant-tree 仅仅是给 ztree 套了一层 Vue 组件的壳,趁便提供了一套更现代化的皮肤,因为主打大数据量场景,所以取名巨树
针对树节点很多,但是每级节点数据不多的情况造成的总数据量大,速率很快。但针对每个节点数据很多,但总节点不多的大量数据情况无效。(比如如今数据是1x 20 x 10 x 25 x 100 五个层级,每个层级最大只有100符合,假如是1x 25x 20000 ,一个节点有2万数据,优化不明显),前端书写的时候都是dom操作,还是有些麻烦的
 
githup链接:https://github.com/tower1229/Vue-Giant-Tree
zTree的api文档链接:Demo [zTree -- jQuery tree plug-ins.]
1.安装插件

  1. npm i vue-giant-tree --save
复制代码
注意:组件依赖 jQuery,务必在页面中提前加载 jQuery,
2.页面使用

zTree组件页面代码
  1. <template>
  2.   <div class="ztree vue-giant-tree" :id="ztreeId"></div>
  3. </template>
  4. <script>
  5. require("@ztree/ztree_v3/js/jquery.ztree.all");
  6. export default {
  7.   props: {
  8.     setting: {
  9.       type: Object,
  10.       require: false,
  11.       default: function () {
  12.         return {};
  13.       },
  14.     },
  15.     nodes: {
  16.       type: Array,
  17.       require: true,
  18.       default: function () {
  19.         return [];
  20.       },
  21.     },
  22.   },
  23.   data() {
  24.     return {
  25.       ztreeId: "ztree_" + parseInt(Math.random() * 1e10),
  26.       ztreeObj: null,
  27.       list: [],
  28.       ztreeSetting: {
  29.         view: {
  30.           showIcon: false, // default to hide icon
  31.         },
  32.         callback: {
  33.           onAsyncError: (...arg) => {
  34.             this.$emit("onAsyncError", ...arg);
  35.           },
  36.           onAsyncSuccess: (...arg) => {
  37.             this.$emit("onAsyncSuccess", ...arg);
  38.           },
  39.           onCheck: (...arg) => {
  40.             this.$emit("onCheck", ...arg);
  41.           },
  42.           onClick: (...arg) => {
  43.             this.$emit("onClick", ...arg);
  44.           },
  45.           onCollapse: (...arg) => {
  46.             this.$emit("onCollapse", ...arg);
  47.           },
  48.           onDblClick: (...arg) => {
  49.             this.$emit("onDblClick", ...arg);
  50.           },
  51.           onDrag: (...arg) => {
  52.             this.$emit("onDrag", ...arg);
  53.           },
  54.           onDragMove: (...arg) => {
  55.             this.$emit("onDragMove", ...arg);
  56.           },
  57.           onDrop: (...arg) => {
  58.             this.$emit("onDrop", ...arg);
  59.           },
  60.           onExpand: (...arg) => {
  61.             this.$emit("onExpand", ...arg);
  62.           },
  63.           onMouseDown: (...arg) => {
  64.             this.$emit("onMouseDown", ...arg);
  65.           },
  66.           onMouseUp: (...arg) => {
  67.             this.$emit("onMouseUp", ...arg);
  68.           },
  69.           onRemove: (...arg) => {
  70.             this.$emit("onRemove", ...arg);
  71.           },
  72.           onRename: (...arg) => {
  73.             this.$emit("onRename", ...arg);
  74.           },
  75.           onRightClick: (...arg) => {
  76.             this.$emit("onRightClick", ...arg);
  77.           },
  78.         },
  79.       },
  80.     };
  81.   },
  82.   watch: {
  83.     nodes: {
  84.       handler: function (nodes) {
  85.         this.list = nodes;
  86.         // update tree
  87.         if (this.ztreeObj) {
  88.           this.ztreeObj.destroy();
  89.         }
  90.         this.$nextTick(() => {
  91.           this.ztreeObj = $.fn.zTree.init(
  92.             $("#" + this.ztreeId),
  93.             Object.assign({}, this.ztreeSetting, this.setting),
  94.             this.list
  95.           );
  96.           this.$emit("onCreated", this.ztreeObj);
  97.         });
  98.       },
  99.       deep: true,
  100.       immediate: true,
  101.     },
  102.   },
  103. };
  104. </script>
  105. <style>
  106. /* beauty ztree! */
  107. .ztree {
  108.   text-align: left;
  109.   font-size: 14px;
  110. }
  111. .vue-giant-tree li {
  112.   list-style-type: none;
  113.   white-space: nowrap;
  114.   outline: none;
  115. }
  116. .vue-giant-tree li ul {
  117.   position: relative;
  118.   padding: 0 0 0 20px;
  119.   margin: 0;
  120. }
  121. .vue-giant-tree .line:before {
  122.   position: absolute;
  123.   top: 0;
  124.   left: 10px;
  125.   height: 100%;
  126.   content: "";
  127.   border-right: 1px dotted #dbdbdb;
  128. }
  129. .vue-giant-tree .roots_docu:before,
  130. .vue-giant-tree .roots_docu:after,
  131. .vue-giant-tree .center_docu:before,
  132. .vue-giant-tree .bottom_docu:before,
  133. .vue-giant-tree .center_docu:after,
  134. .vue-giant-tree .bottom_docu:after {
  135.   position: absolute;
  136.   content: "";
  137.   border: 0 dotted #dbdbdb;
  138. }
  139. .vue-giant-tree .roots_docu:before {
  140.   left: 10px;
  141.   height: 50%;
  142.   top: 50%;
  143.   border-left-width: 1px;
  144. }
  145. .vue-giant-tree .roots_docu:after {
  146.   top: 50%;
  147.   left: 11px;
  148.   width: 50%;
  149.   border-top-width: 1px;
  150. }
  151. .vue-giant-tree .center_docu:before {
  152.   left: 10px;
  153.   height: 100%;
  154.   border-left-width: 1px;
  155. }
  156. .vue-giant-tree .center_docu:after {
  157.   top: 50%;
  158.   left: 11px;
  159.   width: 50%;
  160.   border-top-width: 1px;
  161. }
  162. .vue-giant-tree .bottom_docu:before {
  163.   left: 10px;
  164.   height: 50%;
  165.   border-left-width: 1px;
  166. }
  167. .vue-giant-tree .bottom_docu:after {
  168.   top: 50%;
  169.   left: 11px;
  170.   width: 50%;
  171.   border-top-width: 1px;
  172. }
  173. .vue-giant-tree li a {
  174.   display: inline-block;
  175.   line-height: 22px;
  176.   height: 22px;
  177.   margin: 0;
  178.   cursor: pointer;
  179.   transition: none;
  180.   vertical-align: middle;
  181.   color: #555555;
  182. }
  183. .vue-giant-tree .node_name {
  184.   display: inline-block;
  185.   padding: 0 3px;
  186.   border-radius: 4px;
  187. }
  188. .vue-giant-tree .curSelectedNode .node_name {
  189.   color: #000;
  190.   background-color: #c9e9f7;
  191. }
  192. .vue-giant-tree .curSelectedNode_Edit {
  193.   height: 20px;
  194.   opacity: 0.8;
  195.   color: #000;
  196.   border: 1px #6cc2e8 solid;
  197.   background-color: #9dd6f0;
  198. }
  199. .vue-giant-tree .tmpTargetNode_inner {
  200.   opacity: 0.8;
  201.   color: #fff;
  202.   background-color: #4fcbf0;
  203.   filter: alpha(opacity=80);
  204. }
  205. .vue-giant-tree .rename {
  206.   font-size: 12px;
  207.   line-height: 22px;
  208.   width: 80px;
  209.   height: 22px;
  210.   margin: 0;
  211.   padding: 0;
  212.   vertical-align: top;
  213.   border: 0;
  214.   background: none;
  215. }
  216. .vue-giant-tree .button {
  217.   position: relative;
  218.   display: inline-block;
  219.   line-height: 22px;
  220.   height: 22px;
  221.   width: 22px;
  222.   cursor: pointer;
  223.   text-align: center;
  224.   vertical-align: middle;
  225. }
  226. .vue-giant-tree .button.edit {
  227.   color: #25ae88;
  228. }
  229. .vue-giant-tree .button.remove {
  230.   color: #cb4042;
  231. }
  232. .vue-giant-tree .button.chk {
  233.   position: relative;
  234.   width: 14px;
  235.   height: 14px;
  236.   margin: 0 4px 0 0;
  237.   border: 1px solid #d7dde4;
  238.   border-radius: 2px;
  239.   background: #fff;
  240. }
  241. .vue-giant-tree .chk.radio_true_full,
  242. .vue-giant-tree .chk.radio_false_full,
  243. .vue-giant-tree .chk.radio_true_full_focus,
  244. .vue-giant-tree .chk.radio_false_full_focus,
  245. .vue-giant-tree .chk.radio_false_disable,
  246. .vue-giant-tree .chk.radio_true_disable,
  247. .vue-giant-tree .chk.radio_true_part,
  248. .vue-giant-tree .chk.radio_false_part,
  249. .vue-giant-tree .chk.radio_true_part_focus,
  250. .vue-giant-tree .chk.radio_false_part_focus {
  251.   border-radius: 8px;
  252. }
  253. .vue-giant-tree .button.chk:after {
  254.   position: absolute;
  255.   top: 1px;
  256.   left: 4px;
  257.   width: 4px;
  258.   height: 8px;
  259.   content: "";
  260.   transition: -webkit-transform 0.2s ease-in-out;
  261.   transition: transform 0.2s ease-in-out;
  262.   transition: transform 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out;
  263.   -webkit-transform: rotate(0deg) scale(0);
  264.   transform: rotate(0deg) scale(0);
  265.   border-right: 2px solid #fff;
  266.   border-bottom: 2px solid #fff;
  267. }
  268. .vue-giant-tree .button.checkbox_false_full_focus {
  269.   border-color: #ccc;
  270. }
  271. .vue-giant-tree .button.checkbox_true_full,
  272. .vue-giant-tree .button.checkbox_true_full_focus,
  273. .vue-giant-tree .button.checkbox_true_part,
  274. .vue-giant-tree .button.checkbox_true_part_focus,
  275. .vue-giant-tree .button.checkbox_true_disable {
  276.   border-color: #39f;
  277.   background-color: #39f;
  278. }
  279. .vue-giant-tree .button.checkbox_true_full:after,
  280. .vue-giant-tree .button.checkbox_true_full_focus:after,
  281. .vue-giant-tree .button.checkbox_true_disable:after {
  282.   -webkit-transform: rotate(45deg) scale(1);
  283.   transform: rotate(45deg) scale(1);
  284. }
  285. .vue-giant-tree .button.checkbox_true_part:after,
  286. .vue-giant-tree .button.checkbox_true_part_focus:after {
  287.   top: 5px;
  288.   left: 2px;
  289.   width: 10px;
  290.   height: 1px;
  291.   -webkit-transform: rotate(0deg) scale(1);
  292.   transform: rotate(0deg) scale(1);
  293.   border-right: 0;
  294. }
  295. .vue-giant-tree .button.radio_true_full,
  296. .vue-giant-tree .chk.radio_true_full_focus,
  297. .vue-giant-tree .chk.radio_true_part,
  298. .vue-giant-tree .chk.radio_true_part_focus {
  299.   border-color: #39f;
  300. }
  301. .vue-giant-tree .button.radio_true_full:after,
  302. .vue-giant-tree .chk.radio_true_full_focus:after,
  303. .vue-giant-tree .chk.radio_true_part:after,
  304. .vue-giant-tree .chk.radio_true_part_focus:after {
  305.   top: 3px;
  306.   left: 3px;
  307.   width: 8px;
  308.   -webkit-transform: rotate(0deg) scale(1);
  309.   transform: rotate(0deg) scale(1);
  310.   border: 0;
  311.   border-radius: 4px;
  312.   background: #39f;
  313. }
  314. .vue-giant-tree .button.checkbox_true_disable,
  315. .vue-giant-tree .button.checkbox_false_disable,
  316. .vue-giant-tree .chk.radio_false_disable,
  317. .vue-giant-tree .chk.radio_true_disable {
  318.   cursor: not-allowed;
  319. }
  320. .vue-giant-tree .button.checkbox_false_disable {
  321.   background-color: #f3f3f3;
  322. }
  323. .vue-giant-tree .button.noline_close:before,
  324. .vue-giant-tree .button.noline_open:before,
  325. .vue-giant-tree .button.root_open:before,
  326. .vue-giant-tree .button.root_close:before,
  327. .vue-giant-tree .button.roots_open:before,
  328. .vue-giant-tree .button.roots_close:before,
  329. .vue-giant-tree .button.bottom_open:before,
  330. .vue-giant-tree .button.bottom_close:before,
  331. .vue-giant-tree .button.center_open:before,
  332. .vue-giant-tree .button.center_close:before {
  333.   position: absolute;
  334.   top: 5px;
  335.   left: 5px;
  336.   content: "";
  337.   transition: -webkit-transform ease 0.3s;
  338.   transition: transform ease 0.3s;
  339.   transition: transform ease 0.3s, -webkit-transform ease 0.3s;
  340.   -webkit-transform: rotateZ(0deg);
  341.   transform: rotateZ(0deg);
  342.   -webkit-transform-origin: 25% 50%;
  343.   transform-origin: 25% 50%;
  344.   border: 6px solid;
  345.   border-color: transparent transparent transparent #666;
  346. }
  347. .vue-giant-tree .button.noline_open:before,
  348. .vue-giant-tree .button.root_open:before,
  349. .vue-giant-tree .button.roots_open:before,
  350. .vue-giant-tree .button.bottom_open:before,
  351. .vue-giant-tree .button.center_open:before {
  352.   -webkit-transform: rotateZ(90deg);
  353.   transform: rotateZ(90deg);
  354. }
  355. .vue-giant-tree .button.ico_loading {
  356.   margin-right: 2px;
  357.   background: url("data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7")
  358.     0 center no-repeat;
  359. }
  360. .vue-giant-tree .tmpTargetzTree {
  361.   opacity: 0.8;
  362.   background-color: #2ea9df;
  363.   filter: alpha(opacity=80);
  364. }
  365. .vue-giant-tree .tmpzTreeMove_arrow {
  366.   position: absolute;
  367.   width: 18px;
  368.   height: 18px;
  369.   color: #4fcbf0;
  370. }
  371. </style>
  372. <style>
  373. ul.ztree.zTreeDragUL {
  374.   margin: 0;
  375.   padding: 0;
  376.   position: absolute;
  377.   overflow: hidden;
  378.   background-color: #dedede;
  379.   border: 1px #4fcbf0 dotted;
  380.   border-radius: 4px;
  381.   opacity: 0.7;
  382. }
  383. .zTreeMask {
  384.   position: absolute;
  385.   z-index: 10000;
  386.   opacity: 0;
  387.   background-color: #cfcfcf;
  388. }
  389. </style>
复制代码
在需要使用的页面引入ztree组件
 
  1. <template>
  2. <div style="width:30%;">
  3.       <h1 class="T">
  4.            zTree(vue-giant-tree)延迟加载
  5.       </h1>
  6.      <div class="wrap flex-1">
  7.            <div class="c" style="height:600px;overflow:auto">
  8.                 <tree :setting="setting" :nodes="nodes" @onClick="onClick @onCheck="onCheck" @onCreated="handleCreated" />
  9.                     </div>
  10.                 </div>
  11.             </div>
  12. </template>
  13. <script>
  14. export default {
  15.     name: "app",
  16.     components: {
  17.         VueEasyTree,
  18.         tree: resolve => require(["./ztree.vue"], resolve)
  19.     },
  20.     data() {
  21.         return {
  22.             nodes: [],
  23.             showIndex: 0,
  24.             ztreeObj: null,
  25.             setting: {
  26.                 check: {
  27.                     enable: true
  28.                 },
  29.                 data: {
  30.                     simpleData: {
  31.                         enable: false,
  32.                         pIdKey: "pid",
  33.                     },
  34.                     key:{
  35.                       name:'departName'
  36.                     }
  37.                 },
  38.                 view: {
  39.                     showIcon: false,
  40.                     addHoverDom: this.addHoverDom,
  41.                     removeHoverDom: this.removeHoverDom,
  42.                 }
  43.             }
  44.         };
  45.     },
  46.   methods: {
  47.         addHoverDom(treeid, treeNode) {
  48.             const item = document.getElementById(`${treeNode.tId}_a`);
  49.             if (item && !item.querySelector('.tree_extra_btn')) {
  50.                 const btn = document.createElement('sapn');
  51.                 btn.id = `${treeid}_${treeNode.id}_btn`;
  52.                 btn.classList.add('tree_extra_btn');
  53.                 btn.innerText = '删除';
  54.                 btn.addEventListener('click', (e) => {
  55.                     e.stopPropagation()
  56.                     this.clickRemove(treeNode)
  57.                 })
  58.                 item.appendChild(btn);
  59.             }
  60.         },
  61.         removeHoverDom(treeid, treeNode) {
  62.             const item = document.getElementById(`${treeNode.tId}_a`);
  63.             if (item) {
  64.                 const btn = item.querySelector('.tree_extra_btn');
  65.                 if (btn) {
  66.                     item.removeChild(btn)
  67.                 }
  68.             }
  69.         },
  70.         clickRemove(treeNode) {
  71.             console.log('remove', treeNode)
  72.             this.ztreeObj && this.ztreeObj.removeNode(treeNode)
  73.         },
  74.         onClick: function (evt, treeId, treeNode) {
  75.             // 点击事件
  76.             console.log(evt.type, treeNode);
  77.         },
  78.         onCheck: function (evt, treeId, treeNode) {
  79.             // 选中事件
  80.             console.log(evt.type, treeNode);
  81.         },
  82.         handleCreated: function (ztreeObj) {
  83.             this.ztreeObj = ztreeObj;
  84.             // onCreated 中操作ztreeObj对象展开第一个节点
  85.             ztreeObj.expandNode(ztreeObj.getNodes()[0], true);
  86.             //  ztreeObj.expandAll(true);
  87.         },
  88.         update: function () {
  89.             // 更新示例数据
  90.             this.showIndex = this.showIndex === 0 ? 1 : 0;
  91.         }
  92.     }
  93. };
  94. </script>
  95. <style scoped>
  96. .T {
  97.     font-size: 34px;
  98.     margin: 0 0 30px;
  99.     overflow: hidden;
  100. }
  101. </style>
复制代码
第三种:vxe-table-plugin-virtual-tree
 


这个插件是为相识决vxe-table的v2.0版本不支持虚拟树,vxe-table的3.0版本如今支持虚拟树了,也可以使用vxe-table v3.0。
githup链接:https://github.com/x-extends/vxe-table-plugin-virtual-tree
api链接:
​​​​xe-table v2
这个插件只用了展示树形结构,大概表格树还是比较方便的,但是数据量太大时候,勾选操作还是略卡。但是十万数据以内速率还不错,关键是它可以做成表格树。
 

总结:

具体用哪一种,看你的具体情况了。
假如仅仅是树形展示,那就第一种vue-easy-tree,方便简朴。假如数据量超级大,节点多,但是每个节点的数量不多,还要兼容ie,那就第二种zTree,假如要展示表格树,那就第三种vue-virtual-tree

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表