解决 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,这个版本在原有基础上增加了更多的模型和高清算法,显著提升了图片和视频…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
