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.效果

相关文章:
15.树形虚拟列表实现(支持10000+以上的数据)el-tree(1万+数据页面卡死)
1.问题使用el-tree渲染的树形结构,当数据超过一万条以上的时候页面卡死 2.解决方法: 使用vue-easy-tree来实现树形虚拟列表,注意:vue-easy-tree需要设置高度 3.代码如下 <template><div class"ve-tree" st…...
【服务器07】之【GitHub项目管理】及【Unity异步加载场景】
登录GitHub官网 GitHub: Let’s build from here GitHub 注册账号 登录账号 输入一个自定义名字,点击创建存储库就可以了 现在我们下载Fork Fork - a fast and friendly git client for Mac and Windows (git-fork.com) 免费的 下载完成之后点击File下的Clone …...
ansible提权之become_method与become_flags详解
目录 常见become_methodbecome_flagssu 常见选项总结sudo 常见选项总结pbrun 常见选项总结pfexec 常见选项总结doas 常见选项总结示例使用 sudo 的示例:使用 pbrun 的示例:使用 pfexec 的示例:使用 doas 的示例: 配置方式1. 配置文…...
elementui的el-dialog组件与el-tabs同时用导致浏览器卡死的原因解决
在el-dialog弹出框中,如果使用el-tabs,点击弹框的关闭按钮时,会导致弹出框无法关闭,且浏览器卡死。 解决方式(一): 在el-talbs的面板中不放任何内容: <el-tab-pane label"…...
基于图扑 HT for Web 实现拓扑关系图
拓扑结构在计算机网络设计和通信领域中非常重要,因为它描述了网络中的设备(即“点”)如何相互连接(即通过“线”)。这种结构不仅涉及物理布局,即物理拓扑,还可以涉及逻辑或虚拟的连接方式&#…...
linux笔记10--编辑器之神VIM
文章目录 1. 简单介绍① 为什么叫vim② linux常见的编辑器③ 注意事项④ 其它 2. 操作模式的划分① 两种 -- 国际上普通模式(命令操作模式)插入模式 ② 三种 -- 国内普通模式如何进入与退出界面 插入模式如何进入与退出界面 命令模式如何进入与退出界面常见的命令模式 ③ 区别④…...
安全管理中心-集中管控(6点)
记忆内容: 应划分出特定的管理区域,对分布在网络中的安全设备或安全组件进行管控。(三级新增) 应能够建立一条安全的信息传输路径,对网络中的安全设备或安全组件进行管理。(三级新增) 应对网络…...
使用electron打包Vue前端项目的详细流程
使用electron打包Vue前端项目的详细流程 需要更改的东西 路由模式的修改 # 修改前:url不带#mode: history# 修改后:url带#mode: hash全局修改Cookies为localStorage 由于打包成exe或deb这类可执行文件后,本地是没有 Cookies 全局搜索Cooki…...
《计算机英语》 Unit 4 Information Management 信息管理
Section A Information Storage 信息存储 1. The importance of Information信息的重要性 词汇 reside vi属于,驻留 tablet n平板电脑 laptop n笔记本电脑 repository n仓库 claim n索赔 regulatory n法规 contractua…...
如何打包数据库文件
使用 mysqldump 命令: mysqldump -u username -p database_name > output_file.sql username 是数据库的用户名。database_name 是要导出的数据库名称。output_file.sql 是导出的 SQL 文件名,可以自定义。 示例: mysqldump -u root -p…...
iOS抓包指南 正则过滤爬取
解读iOS抓包 抓包 (packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包也经常被用来进行数据截取等。 什么是正则表达式? 正则表达式(regular expression)是用来描述…...
FLASH仿真EEPROM---基于智芯Z20K11XM
一、介绍 电可擦和可编程只读存储器(EEPROM)可以对字节或字编程和擦除。EEPROM中的数据即使断电也能保持,但Z20K1xx芯片不含EEPROM。然而,闪存可以通过EEPROM仿真软件来模拟EEPROM。Z20K1xx包含两个flash阵列。编程和擦除操作可以在一个数组上进行&#…...
阿里云PAI大模型评测最佳实践
作者:施晨、之用、南茵、求伯、一耘、临在 背景信息 内容简介 在大模型时代,随着模型效果的显著提升,模型评测的重要性日益凸显。科学、高效的模型评测,不仅能帮助开发者有效地衡量和对比不同模型的性能,更能指导他…...
应用图扑 HT for Web 搭建拓扑关系图
拓扑结构在计算机网络设计和通信领域中非常重要,因为它描述了网络中的设备(即“点”)如何相互连接(即通过“线”)。这种结构不仅涉及物理布局,即物理拓扑,还可以涉及逻辑或虚拟的连接方式&#…...
Django Aggregation 使用指南
Django Aggregation 使用指南 在构建Django应用时,我们经常需要对数据库中的数据进行汇总或聚合操作。例如,计算某个字段的平均值、最大值或最小值。这篇文章将详细介绍如何在Django中使用聚合查询,并结合实例进行说明。 聚合查询简介 Dja…...
嵌入式学习——Linux操作系统——文件编程练习
1.使用fread和fwrite方式完成任意普通文件的拷贝功能。 模拟 文件下载 #include <stdio.h>void do_copy(FILE *fp_s,FILE *fp_d) {char buf[100] {0};int ret;while (ret fread(buf,sizeof(char),sizeof(buf),fp_s))fwrite(buf,sizeof(char),ret,fp_d); }//./a.out sr…...
用JavaScript实现了一个简单的图像坐标点标注工具
这段代码实现了一个简单的图像标注工具,允许用户在加载的图像上进行点选标注,并且通过右键确认一个点序列来形成一个多边形。 标注效果如下 实现代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"U…...
Pytorch深度解析:Transformer嵌入层源码逐行解读
前言 本部分博客需要先阅读博客: 《Transformer实现以及Pytorch源码解读(一)-数据输入篇》 作为知识储备。 Embedding使用方式 如下面的代码中所示,embedding一般是先实例化nn.Embedding(vocab_size, embedding_dim)。实例化的…...
HSP_10章 Python面向对象编程oop_基础部分
文章目录 P107 类与实例的关系1.类与实例的关系示意图2.类与实例的代码分析 P109 对象形式和传参机制1. 类与对象的区别和联系2. 属性/成员变量3. 类的定义和使用4. 对象的传递机制 P110 对象的布尔值P111 成员方法1. 基本介绍2. 成员方法的定义和基本使用3.注意事项和使用细节…...
JavaWeb系列十七: jQuery选择器 上
jQuery选择器 jQuery基本选择器jquery层次选择器基础过滤选择器内容过滤选择器可见度过滤选择器 选择器是jQuery的核心, 在jQuery中, 对事件处理, 遍历 DOM和Ajax 操作都依赖于选择器jQuery选择器的优点 $(“#id”) 等价于 document.getElementById(“id”);$(“tagName”) 等价…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
Netty自定义协议解析
目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...
第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...
Go 并发编程基础:select 多路复用
select 是 Go 并发编程中非常强大的语法结构,它允许程序同时等待多个通道操作的完成,从而实现多路复用机制,是协程调度、超时控制、通道竞争等场景的核心工具。 一、什么是 select select 类似于 switch 语句,但它用于监听多个通…...
RabbitMQ work模型
Work 模型是 RabbitMQ 最基础的消息处理模式,核心思想是 多个消费者竞争消费同一个队列中的消息,适用于任务分发和负载均衡场景。同一个消息只会被一个消费者处理。 当一个消息队列绑定了多个消费者,每个消息消费的个数都是平摊的&a…...
