当前位置: 首页 > news >正文

15.树形虚拟列表实现(支持10000+以上的数据)el-tree(1万+数据页面卡死)

1.问题使用el-tree渲染的树形结构,当数据超过一万条以上的时候页面卡死

2.解决方法:

使用vue-easy-tree来实现树形虚拟列表,注意:vue-easy-tree需要设置高度

3.代码如下

<template><div class="ve-tree" style="height:calc(100vh - 20px)"><!-- 不使用虚拟滚动时只需去掉height参数即可 --><vue-easy-treeref="veTree"node-key="id"show-checkboxheight="calc(100vh - 20px)":data="treeData":props="props"></vue-easy-tree></div></template><script>import VueEasyTree from "@wchbrad/vue-easy-tree";
// 样式文件,可以根据需要自定义样式或主题(使用这个样式需要装sass-loader以及node-sass)
import "@wchbrad/vue-easy-tree/src/assets/index.scss"export default {components: {VueEasyTree},data() {return {props: {label: "name",children: "children"},treeData: []};},created() {const data = [],root = 8,children = 3,base = 1000;for (let i = 0; i < root; i++) {data.push({id: `${i}`,name: `test-${i}`,children: []});for (let j = 0; j < children; j++) {data[i].children.push({id: `${i}-${j}`,name: `test-${i}-${j}`,children: []});for (let k = 0; k < base; k++) {data[i].children[j].children.push({id: `${i}-${j}-${k}`,name: `test-${i}-${j}-${k}`});}}}this.treeData = data;}};</script>

4. 使用方法,首先安装依赖

yarn add @wchbrad/vue-easy-tree

如果不引入样式文件可以不安装(sass-loader以及node-sass)
node-sass:4.14.1
sass-loader:8.0.2
(自己安装的时候失败了,所以选择不引入样式文件)

5.组件引入

import VueEasyTree from "@wchbrad/vue-easy-tree";
// 样式文件,可以根据需要自定义样式或主题
import "@wchbrad/vue-easy-tree/src/assets/index.scss"export default {components: {VueEasyTree}
}

6.功能列表

 1.大数据量支持虚拟滚动2.基本树形数据的展示3.支持checkbox选择4.支持懒加载5.默认展开和默认选中6.禁用节点7.通过多种方式选中节点和获取选中的节点信息8.支持自定义节点内容9.支持节点过滤10.非虚拟滚动下,支持手风琴模式11.非懒加载时,支持节点拖拽

支持与element-ui完全相同的主题样式更换,提供与element-ui相同的图标供选用
如果使用element-ui的默认属性代码为

<template><div class="tree-comp"><div class="input-box"><el-input size="mini" suffix-icon="el-icon-search" clearable v-model="filterInputValue"@change="onFilter" placeholder="请输入检索内容"></el-input></div><div class="ve-tree" style="height:520px"><!-- 不使用虚拟滚动时只需去掉height参数即可 --><vue-easy-treev-for="(treeItem, index) in treeOption" :key="index"ref="treeComp"node-key="id"show-checkboxheight="520px":data="treeItem.treeData":props="props":filter-node-method="filterNode":highlight-current="true":default-checked-keys="allNodeIds":default-expanded-keys="defaultExpandedKeys[index]":check-on-click-node="true"v-bind="treeItem.defaultProps"v-on="treeItem.defaultActions"@check-change="handleCheckChange"></vue-easy-tree></div></div>
</template><script>
import VueEasyTree from "@wchbrad/vue-easy-tree";
const debounce = function debounce(fn, delay) {let timer = null;return function () {clearTimeout(timer);let args = arguments;let that = this;timer = setTimeout(function () {fn.apply(that, args);}, delay);};
};
export default {name: 'TreeComp',props: {treeOption: { type: Array },selection: {type: String,default: 'multiple'}},components: {VueEasyTree},data() {return {filterInputValue: '',  // 过滤搜素值curChoosedData: {} ,    // 当前节点数据filterParentNodeId: [],selectedCount: 0,defaultExpandedKeys: [],allNodeIds: [],props: {label: "name",children: "children"},treeData: []}},watch: {curChoosedData(val){this.$emit('curChoosedDataChange', val);},},computed: {isSingle() {return this.selection === 'single'}},created(){const data = [],root = 8,children = 3,base = 9000;for (let i = 0; i < root; i++) {data.push({id: `${i}`,name: `test-${i}`,children: []});for (let j = 0; j < children; j++) {data[i].children.push({id: `${i}-${j}`,name: `test-${i}-${j}`,children: []});for (let k = 0; k < base; k++) {data[i].children[j].children.push({id: `${i}-${j}-${k}`,name: `test-${i}-${j}-${k}`});}}}this.treeData = data;},mounted() {this.getSelectedCount()},methods: {expandedLevel(num = 1){const treeCompRef = this.$refs.treeComp;this.treeOption.forEach((item)=>{item.treeData = this.$lodash.cloneDeep(item.treeData)})if(treeCompRef && treeCompRef.length > 0) {for (const [index,item] of treeCompRef.entries()) {let checkedKeys = item.getCheckedKeys()let treeData = item.datathis.defaultExpandedKeys[index] = this.expandedReduce(treeData, num)item.setCheckedKeys(checkedKeys)}}},//递归获取展开层级的idexpandedReduce(list,deep = 1){return deep > 0 ? list.reduce((val ,next)=>{return next.children? val.concat(next.id).concat(this.expandedReduce(next.children,deep-1)) : val.concat(next.id)},[]) : []},// 过滤值改变触发filterNodeonFilter(filterVal) {const treeCompRef = this.$refs.treeComp;if(treeCompRef && treeCompRef.length >0){for (let item of treeCompRef) {this.filterParentNodeId = [];item.filter(filterVal);}}},// 筛选树节点filterNode(value, data) {if (!value) return true;let filterValue = value.split(',');let flag = false;filterValue.forEach((item) => {if (data.name.indexOf(item) !== -1 || this.filterParentNodeId.includes(data.parentId)) {this.filterParentNodeId.push(data.id);flag = true;} });return flag;},handleCheckChange:function (data, checked) {if (this.isSingle) {this.singleCheck(data,checked)}this.getSelectedCount()},singleCheck:debounce(function (data,checked){this.$nextTick(()=>{if (checked) {this.$refs.treeComp[0].setCheckedKeys([data.id]);}})},100),getSelectedCount: debounce(function () {this.selectedCount = 0const treeCompRef = this.$refs.treeComp;if(treeCompRef && treeCompRef.length >0){for (const item of treeCompRef) {let selectedNodes = item.getCheckedNodes()let selectedChildrenNodes = selectedNodes.filter((node) => {// !Object.prototype.hasOwnProperty.call(node, 'children')// return node.children.length === 0return !node.children || node.children.length === 0})this.selectedCount += selectedChildrenNodes.length}}this.$emit('getSelectedCount', this.selectedCount)},300)}
}
</script>
<style scoped>.tree-comp {display: flex;flex-direction: column;overflow: hidden;width: 100%;height: 100%;}.tree-comp .input-box >>> .el-input__inner {border: none;border-radius: 0;border-bottom: 1px solid #A8AED3;height: 32px;line-height: 32px;}.tree-comp .input-box >>> .el-input__suffix-inner {line-height: 32px;font-size: 16px;}.tree-comp .el-tree {/* flex: 1; */max-height: 100%;overflow-y: auto;}.tree-node {flex: 1;height: 30px;line-height: 30px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;/*background: #fff;*/z-index: 2;}.tree-self {width: 100%;overflow: scroll;}.tree-self >>> .el-tree-node {min-width: 100%;display: table;}
</style>

7.效果

在这里插入图片描述

http://www.lryc.cn/news/381926.html

相关文章:

  • 【服务器07】之【GitHub项目管理】及【Unity异步加载场景】
  • ansible提权之become_method与become_flags详解
  • elementui的el-dialog组件与el-tabs同时用导致浏览器卡死的原因解决
  • 基于图扑 HT for Web 实现拓扑关系图
  • linux笔记10--编辑器之神VIM
  • 安全管理中心-集中管控(6点)
  • 使用electron打包Vue前端项目的详细流程
  • 《计算机英语》 Unit 4 Information Management 信息管理
  • 如何打包数据库文件
  • iOS抓包指南 正则过滤爬取
  • FLASH仿真EEPROM---基于智芯Z20K11XM
  • 阿里云PAI大模型评测最佳实践
  • 应用图扑 HT for Web 搭建拓扑关系图
  • Django Aggregation 使用指南
  • 嵌入式学习——Linux操作系统——文件编程练习
  • 用JavaScript实现了一个简单的图像坐标点标注工具
  • Pytorch深度解析:Transformer嵌入层源码逐行解读
  • HSP_10章 Python面向对象编程oop_基础部分
  • JavaWeb系列十七: jQuery选择器 上
  • Gone框架介绍30 - 使用`goner/gin`提供Web服务
  • Lipowerline5.0 雷达电力应用软件下载使用
  • STM32学习之一:什么是STM32
  • AI绘画Stable Diffusion 超强一键去除图片中的物体,免费使用!
  • 零基础STM32单片机编程入门(一)初识STM32单片机
  • Github上前十大开源Rust项目
  • 硬件开发笔记(二十):AD21导入外部下载的元器件原理图库、封装库和3D模型
  • 竞赛选题 python opencv 深度学习 指纹识别算法实现
  • RK3568开发笔记(三):瑞芯微RK3588芯片介绍,入手开发板的核心板介绍
  • EtherCAT主站IgH解析(二)-- 如何将Igh移植到Linux/Windows/RTOS等多操作系统
  • ansible copy模块参选选项