virtualList 封装使用 虚拟列表 列表优化
虚拟列表 列表优化
- virtualList 组件封装
virtualList 组件封装
本虚拟列表 要求一次性加载完所有数据 不适合分页
新建一个select.vue 组件页面
<template><div> <el-select transfer="true" :popper-append-to-body="true"popper-class="virtualselect"class="virtual-select-custom-style":value="defaultValue"filterable:filter-method="filterMethod"default-first-optionclearable:placeholder="placeholderParams":multiple="isMultiple":allow-create="allowCreate"@visible-change="visibleChange"v-on="$listeners"@clear="clearChange"><virtual-listref="virtualList"class="virtualselect-list":data-key="value":data-sources="selectArr":data-component="itemComponent":keeps="keepsParams":extra-props="{label: label,value: value,labelTwo:labelTwo,isRight: isRight,isConcat: isConcat,isConcatShowText:isConcatShowText,concatSymbol: concatSymbol}"></virtual-list></el-select></div>
</template>
<script>import {validatenull} from '@/utils/validate.js'import virtualList from 'vue-virtual-scroll-list'import ElOptionNode from './el-option-node'export default {components: {'virtual-list': virtualList},model: {prop: 'bindValue',event: 'change'},props: {// 数组list: {type: Array,default() {return []}},// 显示名称1label: {type: String,default: ''},// 显示名称2 labelTwo: {type: String,default: ''},// 标识value: {type: String,default: ''},// 是否拼接label | valueisConcat: {type: Boolean,default: false},isConcatShowText:{type: Boolean,default: false},// 拼接label、value符号concatSymbol: {type: String,default: ' | '},// 显示右边isRight: {type: Boolean,default: false},// 加载条数keepsParams: {type: Number,default: 10},// 绑定的默认值bindValue: {type: [String, Array,Number],default() {if (typeof this.bindValue === 'string') return ''return []}},// 是否多选isMultiple: {type: Boolean,default: false},placeholderParams: {type: String,default: '请选择'},// 是否允许创建条目allowCreate: {type: Boolean,default: true}},data() {return {itemComponent: ElOptionNode,selectArr: [],defaultValue: null // 绑定的默认值}},watch: {'list'() {this.init()},bindValue: {handler(val, oldVal) {this.defaultValue = this.bindValueif (validatenull(val)) this.clearChange()this.init()},immediate: false,deep: true}},mounted() {this.defaultValue = this.bindValuethis.init()},methods: {init() {if (!this.defaultValue || this.defaultValue?.length === 0) {this.selectArr = this.list} else {// 回显问题// 由于只渲染固定keepsParams(10)条数据,当默认数据处于10条之外,在回显的时候会显示异常// 解决方法:遍历所有数据,将对应回显的那一条数据放在第一条即可this.selectArr = JSON.parse(JSON.stringify(this.list))if (typeof this.defaultValue === 'string' && !this.isMultiple) {let obj = {}if (this.allowCreate) {const arr = this.selectArr.filter(val => {return val[this.value] === this.defaultValue})if (arr.length === 0) {const item = {}// item[this.value] = `Create-${this.defaultValue}`item[this.value] = this.defaultValueitem[this.label] = this.defaultValueitem.allowCreate = truethis.selectArr.push(item)this.$emit('selChange', item)} else {this.$emit('selChange', arr[0])}}// 单选for (let i = 0; i < this.selectArr.length; i++) {const element = this.selectArr[i]// if (element[this.value]?.toLowerCase() === this.defaultValue?.toLowerCase()) {if (element[this.value] === this.defaultValue) {obj = elementthis.selectArr?.splice(i, 1)break}}this.selectArr?.unshift(obj)} else if (this.isMultiple) {if (this.allowCreate) {this.defaultValue.map(v => {const arr = this.selectArr.filter(val => {return val[this.value] === v})if (arr?.length === 0) {const item = {}// item[this.value] = `Create-${v}`item[this.value] = vitem[this.label] = vitem.allowCreate = truethis.selectArr.push(item)this.$emit('selChange', item)} else {this.$emit('selChange', arr[0])}})}// 多选for (let i = 0; i < this.selectArr.length; i++) {const element = this.selectArr[i]this.defaultValue?.map(val => {// if (element[this.value]?.toLowerCase() === val?.toLowerCase()) {if (element[this.value]=== val) {obj = elementthis.selectArr?.splice(i, 1)this.selectArr?.unshift(obj)}})}}}},// 搜索filterMethod(query) {if (!validatenull(query?.trim())) {this.$refs.virtualList.scrollToIndex(0) // 滚动到顶部setTimeout(() => {this.selectArr = this.list.filter(item => {return this.isRight || this.isConcat? (item[this.label].trim()?.toLowerCase()?.indexOf(query?.trim()?.toLowerCase()) > -1 || (item[this.labelTwo]+'')?.toLowerCase()?.indexOf(query?.trim()?.toLowerCase()) > -1): item[this.label]?.toLowerCase()?.indexOf(query?.trim()?.toLowerCase()) > -1// return this.isRight || this.isConcat? (item[this.label].trim().indexOf(query.trim()) > -1 || (item[this.value]+'').trim().indexOf(query.trim()) > -1)// : item[this.label].indexOf(query.trim()) > -1})}, 100)} else {setTimeout(() => {this.init()}, 100)}},visibleChange(bool) {if (!bool) {this.$refs.virtualList.reset()this.init()}},clearChange() {if (typeof this.defaultValue === 'string') {this.defaultValue = ''} else if (this.isMultiple) {this.defaultValue = []}this.visibleChange(false)}}}
</script>
<style lang="scss" scoped>.virtual-select-custom-style{width:100% !important;}
.virtual-select-custom-style ::v-deep .el-select-dropdown__item {// 设置最大宽度,超出省略号,鼠标悬浮显示// options 需写 :title="source[label]"min-width: 300px;max-width: 480px;display: inline-block;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
.virtualselect {// 设置最大高度&-list {max-height:245px;overflow-y:auto;}
}
::-webkit-scrollbar {width: 6px;height: 6px;background-color: transparent;cursor: pointer;margin-right: 5px;
}
::-webkit-scrollbar-thumb {background-color: rgba(144,147,153,.3) !important;border-radius: 3px !important;
}
::-webkit-scrollbar-thumb:hover{background-color: rgba(144,147,153,.5) !important;
}
::-webkit-scrollbar-track {background-color: transparent !important;border-radius: 3px !important;-webkit-box-shadow: none !important;
}
::v-deep .el-select__tags {flex-wrap: unset;overflow: auto;
}
</style>
新建一个组件 el-option-node.vue
<template><el-option:key="label+value":label="concatString2(source[label], source[labelTwo])":value="source[value]":disabled="source.disabled":title="concatString2(source[label], source[labelTwo])"><span >{{ concatString(source[label], source[labelTwo]) }}</span><spanv-if="isRight"style="float:right;color:#939393">{{ source[value] }}</span></el-option>
</template>
<script>export default {name: 'ItemComponent',props: {// 每一行的索引index: {type: Number,default: 0},// 每一行的内容source: {type: Object,default() {return {}}},// 需要显示的名称label: {type: String,default: ''},// 需要显示的名称labelTwo: {type: String,default: ''},// 绑定的值value: {type: String,default: ''},// 是否拼接label | valueisConcat: {type: Boolean,default: false},isConcatShowText:{type: Boolean,default: false},// 拼接label、value符号concatSymbol: {type: String,default: ' | '},// 右侧是否显示绑定的值isRight: {type: Boolean,default() {return false}}},methods: {//选择后 只显示label//张三concatString(a, b) {a = a || ''b = b || ''if (this.isConcat) {// return a + ((a && b) ? ' | ' : '') + breturn a + ((a && b) ? this.concatSymbol : '') + b}return a},//选择下拉展示时 可以展示label和labelTwo//123||张三concatString2(a, b) {a = a || ''b = b || ''if (this.isConcat) {// return a + ((a && b) ? ' | ' : '') + bif(this.isConcatShowText==true){return a + ((a && b) ? this.concatSymbol : '') + b}else{return a}}return a}}}
</script>
组件建议完成后 在页面使用:
list:数据 [{name:‘张三’,code:‘098’},{}] label:要显示的字段1 labelTwo:要显示的字段2
concat-symbol:拼接符号 is-concat是否拼接 is-multiple:是否多选 allowCreate是否可以创建目录 @change 事件 keeps-params数据多少条
<template><div><virtual-select v-model="item.contractGodsId":list="goodsList" label="name" labelTwo="code" value="id" :placeholder-params="'请选择产品'":keeps-params="10" :is-concat="true" :isConcatShowText="false":concat-symbol="' || '" :is-multiple="false" :allowCreate="false"@change="goodsChange($event,$index)" /></div>
</template>引入组件import VirtualSelect from '@/views/components/virtualList/select'export default {components: {VirtualSelect},}
如果label和labelTwo都填写了,显示效果如下
本虚拟列表 要求一次性加载完所有数据 不适合分页
相关文章:

virtualList 封装使用 虚拟列表 列表优化
虚拟列表 列表优化 virtualList 组件封装 virtualList 组件封装 本虚拟列表 要求一次性加载完所有数据 不适合分页 新建一个select.vue 组件页面 <template><div> <el-select transfer"true" :popper-append-to-body"true"popper-class…...

HCIP-九、路由控制
九、路由控制 实验拓扑实验需求及解法1.企业生产网运行 OSPF,完成以下需求:2.数据中心运行 ISIS3.路由引入4.路由策略5.策略路由6.ISP 过滤私网路由 实验拓扑 实验需求及解法 1.企业生产网运行 OSPF,完成以下需求: 1.1 OSPF 进程…...

Vue3水印(Watermark)
APIs 参数说明类型默认值必传width水印的宽度,默认值为 content 自身的宽度numberundefinedfalseheight水印的高度,默认值为 content 自身的高度numberundefinedfalserotate水印绘制时,旋转的角度,单位 number-22falsezIndex追加…...

redis的性能管理、主从复制和哨兵模式
一、redis的性能管理 redis的数据时缓存在内存中的 查看系统内存情况 info memory used_memory:853688 redis中数据占用的内存 used_memory_rss:10522624 redis向操作系统申请的内存 used_memory_peak:853688 redis使用内存的峰值 系统巡检:硬件巡检、数据库 n…...

排序算法:归并排序、快速排序、堆排序
归并排序 要将一个数组排序,可以先将它分成两半分别排序,然后再将结果合并(归并)起来。这里的分成的两半,每部分可以使用其他排序算法,也可以仍然使用归并排序(递归)。 我看《算法》…...

Redis 面试题——持久化
目录 1.概述1.1.Redis 的持久化功能是指什么?1.2.Redis 有哪些持久化机制? 2.RDB2.1.什么是 RDB 持久化?2.2.Redis 中使用什么命令来生成 RDB 快照文件?2.3.如何在 Redis 的配置文件中对 RDB 进行配置?2.4.✨RDB 持久化…...

Linux使用固定ip地址
设置静态ip,我们就需要修改 /etc/sysconfig/network-scripts/ifcfg-ens33 配置文件。 vim /etc/sysconfig/network-scripts/ifcfg-ens33 //进入网卡ens33的配置页面 (1) 将 BOOTPROTO dhcp 改成 BOOTPROTO static 也就是将动态ip,改成静态i…...

ESP Multi-Room Music 方案:支持音频实时同步播放 实现音乐互联共享
项目背景 随着无线通信技术的发展,针对不同音频应用领域的无线音频产品正不断涌现。近日,乐鑫科技推出了基于 Wi-Fi 的多扬声器互联共享音乐通信协议——ESP Multi-Room Music 方案。该方案使用乐鑫自研的基于 Wi-Fi 局域网的音频同步播放技术ÿ…...

java分布式锁分布式锁
java分布式&锁&分布式锁 锁 锁的作用:有限资源的情况下,控制同一时间段,只有某些线程(用户/服务器)能访问到资源。 锁在java中的实现: synchronized关键字并发包的类 缺点:只对单个的…...

2. 流程控制|方法|数组|二维数组|递归
文章目录 流程控制代码块选择结构循环结构跳转控制关键字 方法方法的概述方法的重载Junit单元测试初识全限定类名 Debug 小技巧数组数组的基本概念数组的基本使用数组的声明数组的初始化 JVM内存模型什么是引用数据类型基本数据类型和引用数据类型的区别堆和栈中内容的区别 数组…...
22. 自动装配有哪些限制(需要注意)?
自动装配有哪些限制(需要注意)? 一定要声明set方法覆盖: 你仍可以用 < constructor-arg >和 < property > 配置来定义依赖,这些配置将始终覆盖自动注入。基本数据类型:不能自动装配简单的属性,如基本数据…...

14 网关实战:网关聚合API文档
上节课介绍了网关层的认证鉴权,今天这节介绍一下网关层如何聚合API接口文文档。 为什么需要聚合API接口文档? 大型微服务系统模块众多,木谷博客系统就有9个,如果这些服务的接口地址没有一个统一,那么客户端将要保存每个服务的接口地址,这个肯定是不现实。 先来看一下A…...
css 固定按钮到页面顶部或者底部的实现方式
实现方式 要将按钮固定到顶部或底部,可以使用CSS的定位属性来实现。下面是一种常用的方法: 创建一个包含按钮的HTML元素,例如一个<div>元素。确保给它添加一个唯一的id,以便在CSS中进行定位。 <div id"myButton&qu…...

【Java Spring】SpringBoot常用插件
文章目录 1、Lombok1.1 IDEA社区版安装Lombok1.2 IDEA专业版安装Lombok1.3 Lombok的基本使用 2、EditStarters2.1 IDEA安装EditStarters2.2 EditStarters基本使用方法 1、Lombok 是简化Java开发的一个必要工具,lombok的原理是编译过程中将lombok的注解给去掉并翻译…...

GPT还远远不是真正的智能
GPT是一个基于深度学习的自然语言处理模型,它可以生成逼真的文本。虽然GPT在生成文本方面取得了显著的进展,但它并不具备真正的智能。GPT是通过训练模型来学习语言模式,它不具备理解、推理、判断和主动学习的能力。它只是根据已有的语料库生成…...

计算机网络:网络层
0 本节主要内容 问题描述 解决思路 1 问题描述 两大问题(重点,也是难点): 地址管理;路由选择。 1.1 子问题1:地址管理 网络上的这些主机和节点都需要使用一种规则来区分,就相当于是一种身…...

消息队列进阶-1.消息队列的应用场景与选型
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理🔥如果感觉博主的文章还不错的话,请ὄ…...
浅谈堆和栈内存以及编程语言
浅谈堆和栈内存以及编程语言 栈和堆C 和 C# 的区别:C#总结 编程语言C汇编语言(Assembly Language):机器语言(Machine Language): 拓展C#依赖注入(Dependency Injection)模…...

SpringBootWeb案例_01
Web后端开发_04 SpringBootWeb案例_01 原型展示 成品展示 准备工作 需求&环境搭建 需求说明: 完成tlias智能学习辅助系统的部门管理,员工管理 环境搭建 准备数据库表(dept、emp)创建springboot工程,引入对应…...

C语言数据结构-----栈和队列练习题(分析+代码)
前言 前面的博客写了如何实现栈和队列,下来我们来看一下队列和栈的相关习题。 链接: 栈和队列的实现 文章目录 前言1.用栈实现括号匹配2.用队列实现栈3.用栈实现队列4.设计循环队列 1.用栈实现括号匹配 此题最重要的就是数量匹配和顺序匹配。 用栈可以完美的做到…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...

Tauri2学习笔记
教程地址:https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引:https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多,我按照Tauri1的教程来学习&…...