解决 ElSelect 数据量大导致加载速度慢
遇到一个性能相关的问题,使用 Element Plus 的 <ElSelect> 组件在数据量很大时,加载速度变慢。
下面简单分析下原因,并提供了一些解决方法。
1. 问题分析
1、大量 DOM 节点渲染
问题:当数据量非常大时,每一个选项都会生成一个 DOM 节点。在 HTML 中,每一个 <option> 元素都需要单独渲染,导致页面需要处理大量 DOM 元素的加载和渲染,影响页面性能。
影响:浏览器在渲染和操作大量 DOM 时效率会降低,导致组件初始化和操作(如滚动、过滤)变慢。
2、Vue 响应式系统的性能瓶颈
问题:Vue 的响应式系统会追踪每个数据项的状态变化。当 <ElSelect> 中的数据量过大时,Vue 的响应式系统需要为每一个 Option 建立响应式追踪,增加内存和计算的开销,尤其是在更新数据、滚动或筛选时,这种情况会更加明显。
影响:响应式追踪在数据项非常多的情况下可能导致浏览器出现卡顿,甚至出现页面响应不及时的情况。
3、事件监听和计算
问题:当 <ElSelect> 中的数据项很多时,每次选择、过滤或输入,都会触发事件监听器和计算操作。如果数据项非常多,这些操作会变得频繁且耗时,增加组件的负担。
影响:页面响应速度降低,用户在操作组件时会感觉到明显的卡顿。
4、过多的无意义的渲染
问题:在默认实现中,<ElSelect> 会一次性渲染所有数据项,不管用户是否在当前视口中看到这些数据。即便用户只滚动一小部分,整个组件仍然会处理所有数据项,导致加载速度慢。
影响:浏览器资源被过度消耗,渲染效率降低,页面加载时间延长。
2. 解决方案
1、使用虚拟滚动
方法:借助虚拟滚动技术(如 Element Plus 的 ElVirtualizedSelect 组件),只渲染当前视口中可见的部分数据。虚拟滚动技术通过动态加载和卸载数据项来减少页面上的 DOM 节点数量。
这种方法能显著减少 DOM 渲染的节点数量和内存占用,提升渲染速度和用户体验。
🌰
<template><!-- 使用虚拟滚动的选择框 --><el-select-v2v-model="selectedValue":options="options"placeholder="请选择"style="width: 200px"/>
</template><script>
import { ref } from 'vue';export default {setup() {// 创建 10,000 条模拟数据const options = ref(Array.from({ length: 10000 }, (_, index) => ({value: index,label: `选项 ${index + 1}`})));const selectedValue = ref(null);return {options,selectedValue};}
};
</script>
效果:显著减少 DOM 中节点数量,提升了渲染性能。对于大数据场景,只有可见选项会被加载和渲染,大大降低了内存和渲染开销。
文档:https://element-plus.org/zh-CN/component/select-v2.html
对比:普通的 <ElSelect> 组件,在最开始渲染全部的 Option 元素。
<template><!-- 使用普通的选择框 --><el-select v-model="value" placeholder="Select" style="width: 240px"><el-optionv-for="item in options":key="item.value":label="item.label":value="item.value"/></el-select>
</template><script>
import { ref } from 'vue'
export default {setup() {// 创建 100 条模拟数据,防止页面卡住const options = ref(Array.from({ length: 100 }, (_, index) => ({value: index,label: `选项 ${index + 1}`})))const selectedValue = ref(null)return {options,selectedValue}}
}
</script>
而 <el-select-v2> 组件只渲染展示的一部分,显而易见的提升了渲染性能。
2、分页加载或懒加载
方法:将数据进行分页或分批次加载。比如,可以设置一个加载阈值,先加载一部分数据项,用户向下滚动到一定程度再加载下一部分数据项。
避免一次性加载大量数据,减少页面初始化时的加载压力。
🌰
<template><el-selectv-model="selectedValue"placeholder="请选择"filterable@visible-change="handleVisibleChange"><el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /></el-select>
</template>
<script>
import { ref, nextTick } from 'vue'
export default {setup() {const options = ref([])const page = ref(1)const selectedValue = ref(null)// 模拟 API 获取分页数据const loadOptions = async () => {const newOptions = await fetchOptions(page.value)options.value.push(...newOptions)page.value++}// 处理滚动事件const handleScroll = (event) => {const { scrollTop, clientHeight, scrollHeight } = event.targetif (scrollTop + clientHeight >= scrollHeight - 10) {loadOptions()}}// 监听下拉框的可见性变化const handleVisibleChange = async () => {await nextTick()const dropdown = document.querySelector('.el-select-dropdown .el-scrollbar__wrap')if (dropdown) {dropdown.addEventListener('scroll', handleScroll)}}// 初始加载loadOptions()return {options,selectedValue,handleVisibleChange}}
}
// 模拟 API 调用,获取分页数据
async function fetchOptions(page) {return Array.from({ length: 10 }, (_, index) => ({value: (page - 1) * 10 + index,label: `选项 ${(page - 1) * 10 + index + 1}`}))
}
</script>
效果:初次加载仅渲染一部分数据,滚动到列表底部时加载更多。通过分页,可以避免一次性加载全部数据,减少页面初始化的负担。
展示:
以此类推,直到数据加载完成后结束。
3、减少不必要的响应式追踪
方法:将不需要响应式的数据项转换为非响应式对象或深度克隆数据。Vue 3 提供了 shallowRef 和 shallowReactive,可用来减少不必要的响应式开销。
效果:降低 Vue 响应式系统的性能开销,提升加载和操作的流畅度。
🌰
<template><el-select v-model="selectedValue" placeholder="请选择"><el-optionv-for="item in nonReactiveOptions":key="item.value":label="item.label":value="item.value"/></el-select>
</template><script>
import { shallowRef, ref } from 'vue';
export default {setup() {// 使用 shallowRef 包装不需要响应式的数据const nonReactiveOptions = shallowRef(Array.from({ length: 1000 }, (_, index) => ({value: index,label: `选项 ${index + 1}`})));const selectedValue = ref(null);return {nonReactiveOptions,selectedValue};}
};
</script>
使用 shallowRef 后,Vue 不会深度监听 nonReactiveOptions 的变化,仅在整个对象被替换时触发重新渲染,这样减少 Vue 对数据的追踪和性能开销。
展示:一次性加载完,但不会跟踪内部变化。
4、减少过度的事件监听
方法:对用户输入和操作添加防抖或节流处理,避免频繁地触发数据项的更新和过滤。比如使用 lodash.debounce 限制输入框触发的过滤频率。
🌰
<template><el-select v-model="selectedValue" filterable @input="onInput" placeholder="请选择"><el-optionv-for="item in filteredOptions":key="item.value":label="item.label":value="item.value"/></el-select>
</template><script>
import { ref, computed } from 'vue';
import debounce from 'lodash/debounce';export default {setup() {const options = ref(Array.from({ length: 1000 }, (_, index) => ({value: index,label: `选项 ${index + 1}`})));const searchQuery = ref('');const selectedValue = ref(null);// 使用防抖处理输入事件const onInput = debounce((value) => {searchQuery.value = value;}, 300);const filteredOptions = computed(() =>options.value.filter((item) =>item.label.includes(searchQuery.value)));return {filteredOptions,selectedValue,onInput};}
};
</script>
效果:只有在输入停止 300 毫秒后,才会触发过滤逻辑,从而避免了输入框内容频繁更新导致的高计算开销。这个方法适用于需要实时过滤的场景。
展示:
总结:
当 Element Plus 的 <ElSelect> 组件加载大量数据时,主要是 DOM 渲染、Vue 响应式追踪和事件计算等导致性能下降。通过使用虚拟滚动、分页加载、减少响应式追踪以及事件防抖等方法,可以显著优化加载性能,使组件在大数据量下也能流畅运行。
相关文章:

解决 ElSelect 数据量大导致加载速度慢
遇到一个性能相关的问题,使用 Element Plus 的 <ElSelect> 组件在数据量很大时,加载速度变慢。 下面简单分析下原因,并提供了一些解决方法。 1. 问题分析 1、大量 DOM 节点渲染 问题:当数据量非常大时,每一个…...
在 CentOS 系统中,您可以使用多种工具来查看网络速度和流量
在 CentOS 系统中,您可以使用多种工具来查看网络速度和流量 在 CentOS 系统中,您可以使用多种工具来查看网络速度和流量1. 使用 iftop安装 iftop使用 iftop 2. 使用 nload安装 nload使用 nload 3. 使用 vnstat安装 vnstat初始化 vnstat查看流量 4. 使用 …...

分布式----Ceph部署
目录 一、存储基础 1.1 单机存储设备 1.2 单机存储的问题 1.3 商业存储解决方案 1.4 分布式存储(软件定义的存储 SDS) 1.5 分布式存储的类型 二、Ceph 简介 三、Ceph 优势 四、Ceph 架构 五、Ceph 核心组件 #Pool中数据保存方式支持两种类型&…...

使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类
AlexNet 是一种经典的深度学习模型,它在 2012 年的 ImageNet 图像分类比赛中大放异彩,彻底改变了计算机视觉领域的格局。AlexNet 的核心创新包括使用深度卷积神经网络(CNN)来处理图像,并采用了多个先进的技术如 ReLU 激…...

Python爬虫项目 | 一、网易云音乐热歌榜歌曲
文章目录 1.文章概要1.1 实现方法1.2 实现代码1.3 最终效果 2.具体讲解2.1 使用的Python库2.2 代码说明2.2.1 创建目录保存文件2.2.2 爬取网易云音乐热歌榜单歌曲 2.3 过程展示 3 总结 1.文章概要 学习Python爬虫知识,实现简单的一个小案例,网易云音乐热…...

【Linux】HTTP协议和HTTPS加密
文章目录 HTTP1、概念2、认识URL3、协议格式、请求方法和状态码4、HTTP请求和响应报头5、Cookie和Session HTTPS1、对称和非对称加密2、对称非对称加密安全分析3、证书 HTTP 1、概念 我们在应用层定制协议时,不建议直接发送结构体对象,因为在不同的环境…...

Linux编辑/etc/fstab文件不当,不使用快照;进入救援模式
目录 红帽镜像9救援模式 现象 解决 第一步:修改启动参数以进入救援模式 第二步:进入救援模式、获取root权限、编辑/etc/fstab文件 第三步:编辑好后在重启 下面是ai给的模板 红帽镜像9救援模式 编辑/etc/fstab不当时 17 /dev/nvme0n3p1…...
ubuntu升级postgres
已经有了postgres12,记录一下升级从postgres12升级到15的过程及遇到的一些问题,我没有备份,单纯升级 1、升级过程 深色版本 sudo systemctl stop postgresql 升级PostgreSQL 停止PostgreSQL服务: 停止当前版本的PostgreSQL服务…...
vue2在el-dialog打开的时候使该el-dialog中的某个输入框获得焦点方法总结
在 Vue 2 中,如果你想通过 ref 调用一个方法(如 inputFocus)来聚焦一个输入框,确保以下几点: 确保 ref 的设置正确:你需要确保在模板中正确设置了 ref,并且它指向了你想要操作的组件或 DOM 元素…...

SpringBoot(十七)创建多模块Springboot项目
在gitee上查找资料的时候,发现有不少Springboot项目里边都是嵌套了多个Springboot项目的。这个玩意好,在协作开发的时候,将项目分成多个模块,有多个团队协作开发,模块间定义标准化通信接口进行数据交互即可。 这个好这个。我之前创建的博客项目是单模块的SpringBoot项目,…...
Vue.js 高质量翻页功能的完整开发指南
文章目录 Vue.js 翻页组件的完整开发与优化指南前言分析分页需求与设计要点基础分页功能的实现分页逻辑 优化分页:封装为组件化设计组件化代码 提升用户体验与性能动态调整每页显示的条目数优化移动端与桌面端的展示高性能翻页策略:按需加载与懒加载提示…...
android dvr黑屏
问题现象:dvr拍摄的图片是黑的,没有buffer数据的。 查看相关的log文件发现: video surface 未释放导致 祥见一下报错信息: 38298 2024-10-16 01:02:51.855 4056 32068 W MediaCodecRenderer: java.lang.IllegalStateExcepti…...

css文字间距撑满横向距离
效果: 代码: 、 text-align:justify;text-align-last: justify;...
【Unity基础】对比OnCollisionEnter与OnTriggerEnter
在Unity中,OnCollisionEnter 和 OnTriggerEnter 是两种用于处理碰撞的回调函数,但它们的工作方式和使用场景有所不同: 1. OnCollisionEnter 触发条件:当一个带有 Collider 组件并且**未勾选“Is Trigger”**的物体,与…...
算法训练(leetcode)二刷第二十五天 | *134. 加油站、*135. 分发糖果、860. 柠檬水找零、*406. 根据身高重建队列
刷题记录 *134. 加油站*135. 分发糖果860. 柠檬水找零*406. 根据身高重建队列 *134. 加油站 leetcode题目地址 当前站点可以剩余油量gas[i] - cost[i]; 将每站的剩余油量求和计算累计剩余油量,总剩余油量小于0,则无法行驶一周。 若在到达某一站时累计剩…...
Springboot 整合 itext 实现PDF文件合并,识别图片则转成PDF拼接
目录 前言一、引用依赖二、使用步骤1.Controller2.Service接口3.实现类三、请求接口及结果前言 本文实现 Springboot 整合 itext 实现PDF文件合并,图片转PDF拼接。 一、引用依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itext7-co…...
TypeScript 中的 ! 和 ? 操作符
在 TypeScript 中,! 和 ? 是两个非常重要且常用的操作符,分别用于非空断言和可选链操作。下面简单介绍一下二者。 1. 非空断言操作符 ! 1.1 含义 非空断言操作符 !(Non-null assertion operator)用来告诉 TypeScript 编译器&a…...

开源三代示波器的高速波形刷新方案开源,支持VNC远程桌面,手机,Pad,电脑均可访问(2024-11-11)
说明: 1、本来这段时间是一年一度Hackaday硬件设计开源盛宴,但hackaday电子大赛在去年终结了。所以我开源个我的吧。 2、三代示波器的高速波形刷新方案,前两年就做好了,这两年忙H7-TOOL的更新比较多,三代示波器的更新…...

谷歌推出设备内置人工智能,实时向手机用户发出诈骗电话警报
Google 宣布推出适用于 Android 的新安全功能,可实时防御诈骗和有害应用。 这些功能由先进的设备内置 AI 提供支持,可在不损害隐私的情况下增强用户安全性。 这些新的安全功能首先在 Pixel 上推出,并将很快在更多 Android 设备上推出。 诈…...

AI换人脸facefusion项目口型同步API化改造及部署
一. 简介 FaceFusion是一款强大的AI换脸软件,它支持图片、视频以及直播换脸,官方将其称为“下一代脸部交换器和增强器”。FaceFusion的最新版本为2.6.1,这个版本在原有基础上增加了更多的模型和高清算法,显著提升了图片和视频…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...