首页 > 其他分享 >vue插件 vue-virtual-scroll-list解决数据量太大问题

vue插件 vue-virtual-scroll-list解决数据量太大问题

时间:2024-04-11 18:34:52浏览次数:27  
标签:selectArr 插件 vue toLowerCase list 数据量 selectData data

项目中数据量有时候过于庞大,使用elementui的Select组件时,会导致下拉框加载速度慢卡顿甚至于卡死,为解决这个问题,使用vue-virtual-scroll-list插件 ,模拟虚拟滚动。

vue-virtual-scroll-list是vue的一个虚拟滚动组件,通过不渲染可视区域以外的内容,显示虚拟的滚动条来提升页面性能

首先看

安装

npm install vue-virtual-scroll-list --save

参数及方法

常用参数

PropTypeDescription
data-key String|Function 从data-sources每个数据对象中获取唯一键。或每个函数都调用data-source并返回其唯一键。在中,其值必须唯一data-sources,用于标识商品尺寸。
data-sources Array[Object] 列表数据,每一行都必须有一个唯一的id(data-key)
data-component Component 每一行的子组件
keeps Number 默认30个,默认渲染的个数
extra-props Object 默认{} data-component组件的额外props通过改属性传入,内部已有source和index两个

常用方法

可以通过以下方式调用这些方法ref:

MethodDescription
reset() 将所有状态重置为初始状态。
scrollToIndex(index) 手动设置滚动位置到指定索引。

上述是组件用到的方法,其他参数及方法可查看官网

引入使用

1 import virtualList from 'vue-virtual-scroll-list'
2 components:{
3     'virtual-list': virtualList
4 },

基础用法

  • 属性说明

data-key=“selectData.value” 就是绑定的唯一key值,可传入动态的

data-sources=“selectArr” 下拉框的数组

data-component=“itemComponent” 就是抽离中的el-option组件

keeps=“20” 渲染的个数

extra-props 值为对象,可以传入自定义属性进去

  • 高度设置
 1 .virtualselect {
 2     // 设置最大高度
 3     &-list {
 4         max-height:245px;
 5         overflow-y:auto;
 6     }
 7     .el-scrollbar .el-scrollbar__bar.is-vertical {
 8         width: 0;
 9     }
10 }

原理

 

只渲染keeps传入的个数,滚动时通过改变padding的值来模拟滚动,里面的每一个item在滚动时动态替换里面的值,永远只渲染keeps传入的个数,所以这样不会卡

  • 回显问题

由于只渲染20条数据,当默认数据处于20条之外,在回显的时候会显示异常
解决方法: 遍历所有数据,将对应回显的那一条数据放在第一条即可

 1 this.selectArr = JSON.parse(JSON.stringify(this.selectData.data));
 2 let obj = {};
 3 for (let i = 0; i < this.selectArr.length; i++) {
 4     const element = this.selectArr[i];
 5     if(element[this.selectData.value].toLowerCase() === this.defaultValue.toLowerCase()) {
 6         obj = element;
 7         this.selectArr.splice(i,1);
 8         break;
 9     }
10 }
11 this.selectArr.unshift(obj);
  • 模糊搜索

使用select自带的filterable,filter-method自定义属性实现过滤数据

 1 <el-select filterable :filter-method="filterMethod" @visible-change="visibleChange" >
 2 </el-select>
 3 
 4 // 搜索
 5 filterMethod(query) {
 6     if (query !== '') {
 7         this.$refs.virtualList.scrollToIndex(0);//滚动到顶部
 8         setTimeout(() => {
 9             this.selectArr = this.selectData.data.filter(item => {
10                 return this.selectData.isRight?
11                     (item[this.selectData.label].toLowerCase().indexOf(query.toLowerCase()) > -1 || item[this.selectData.value].toLowerCase().indexOf(query.toLowerCase()) > -1)
12                     :item[this.selectData.label].toLowerCase().indexOf(query.toLowerCase()) > -1;
13             });
14         },100)
15     } else {
16         this.init();
17     }
18 },
19 visibleChange(bool) {
20     if(!bool) {
21         this.$refs.virtualList.reset();
22         this.init();
23     }
24 }

完整代码

  • Select.vue
      1 <template>
      2     <div>
      3         <el-select :value="defaultValue" popper-class="virtualselect" filterable :filter-method="filterMethod" @visible-change="visibleChange" v-bind="$attrs" v-on="$listeners">
      4             <virtual-list ref="virtualList" class="virtualselect-list"
      5                 :data-key="selectData.value"
      6                 :data-sources="selectArr"
      7                 :data-component="itemComponent"
      8                 :keeps="20"
      9                 :extra-props="{
     10                     label: selectData.label,
     11                     value: selectData.value,
     12                     isRight: selectData.isRight
     13                 }"></virtual-list>
     14         </el-select>
     15     </div>
     16 </template>
     17 <script>
     18 import virtualList from 'vue-virtual-scroll-list'
     19 import ElOptionNode from './el-option-node'
     20 export default {
     21     components:{
     22         'virtual-list': virtualList
     23     },
     24     model: {
     25         prop: 'defaultValue',
     26         event: 'change',
     27     },
     28     props: {
     29         selectData: {
     30             type: Object,
     31             default () {
     32                 return {}
     33             }
     34         },//父组件传的值
     35         defaultValue: {
     36             type: String,
     37             default: ''
     38         }// 绑定的默认值
     39     },
     40     mounted() {
     41         this.init();
     42     },
     43     watch: {
     44         'selectData.data'() {
     45             this.init();
     46         }
     47     },
     48     data() {
     49         return {
     50             itemComponent: ElOptionNode,
     51             selectArr:[]
     52         }
     53     },
     54     methods: {
     55         init() {
     56             if(!this.defaultValue) {
     57                 this.selectArr = this.selectData.data;
     58             }else {
     59                 // 回显问题
     60                 // 由于只渲染20条数据,当默认数据处于20条之外,在回显的时候会显示异常
     61                 // 解决方法:遍历所有数据,将对应回显的那一条数据放在第一条即可
     62                 this.selectArr = JSON.parse(JSON.stringify(this.selectData.data));
     63                 let obj = {};
     64                 for (let i = 0; i < this.selectArr.length; i++) {
     65                     const element = this.selectArr[i];
     66                     if(element[this.selectData.value].toLowerCase() === this.defaultValue.toLowerCase()) {
     67                         obj = element;
     68                         this.selectArr.splice(i,1);
     69                         break;
     70                     }
     71                 }
     72                 this.selectArr.unshift(obj);
     73             }
     74         },
     75         // 搜索
     76         filterMethod(query) {
     77             if (query !== '') {
     78                 this.$refs.virtualList.scrollToIndex(0);//滚动到顶部
     79                 setTimeout(() => {
     80                     this.selectArr = this.selectData.data.filter(item => {
     81                         return this.selectData.isRight?
     82                             (item[this.selectData.label].toLowerCase().indexOf(query.toLowerCase()) > -1 || item[this.selectData.value].toLowerCase().indexOf(query.toLowerCase()) > -1)
     83                             :item[this.selectData.label].toLowerCase().indexOf(query.toLowerCase()) > -1;
     84                     });
     85                 },100)
     86         } else {
     87             this.init();
     88         }
     89         },
     90         visibleChange(bool) {
     91             if(!bool) {
     92                 this.$refs.virtualList.reset();
     93                 this.init();
     94             }
     95         }
     96     }
     97 }
     98 </script>
     99 <style lang="scss" scoped>
    100     .virtualselect {
    101         // 设置最大高度
    102         &-list {
    103             max-height:245px;
    104             overflow-y:auto;
    105         }
    106         .el-scrollbar .el-scrollbar__bar.is-vertical {
    107             width: 0;
    108         }
    109     }
    110     
    111 </style>

     

  • el-option-node.vue

     1 <template>
     2     <el-option :key="label+value" :label="source[label]" :value="source[value]">
     3         <span>{{source[label]}}</span>
     4         <span v-if="isRight" style="float:right;color:#939393">{{source[value]}}</span>
     5     </el-option>
     6 </template>
     7 <script>
     8 export default {
     9     name: 'item-component',
    10     props: {
    11         index: {
    12             type: Number
    13         },// 每一行的索引
    14         source: {
    15             type: Object,
    16             default () {
    17                 return {}
    18             }
    19         },// 每一行的内容
    20         label: {
    21             type: String
    22         },// 需要显示的名称
    23         value: {
    24             type: String
    25         },// 绑定的值
    26         isRight: {
    27             type: Boolean,
    28             default () {
    29                 return false
    30             }
    31         }// 右侧是否显示绑定的值
    32     }
    33 }
    34 </script>

     

  • parent.vue

  

 1 <template>
 2     <cw-select :selectData="selectData" v-model="defaultValue" placeholder="请选择下拉数据" clearable @change="selectChange"></cw-select>
 3 </template>
 4 
 5 <script>
 6     import CwSelect from '@/components/Select'
 7     export default {
 8         components: {
 9             CwSelect
10         },
11         data() {
12             return {
13                 selectData: {
14                     data:[],// 下拉框数据
15                     label: 'name',// 下拉框需要显示的名称
16                     value: 'code',// 下拉框绑定的值
17                     isRight: true,//右侧是否显示
18                 },
19                 defaultValue: 'China99', //下拉框选择的默认值
20             };
21         },
22         mounted() {
23             this.selectData.data = []
24             for (let i = 0; i < 10000; i++) {
25                 this.selectData.data.push({code:'China'+i,name:'中国'+i+''})
26             }
27         },
28         methods: {
29             selectChange(val) {
30                 console.log('下拉框选择的值', val)
31             }
32         }
33     };
34 </script>

 

标签:selectArr,插件,vue,toLowerCase,list,数据量,selectData,data
From: https://www.cnblogs.com/yuwenjing0727/p/18129844

相关文章

  • docker 中使用 php--apache并加入 mysql 插件
    官方镜像说明页:可根据自己需要,选择对应版本的php进行下载。这里使用php7.4+apache服务的镜像为例:dockerpullphp:7.4.33-apache运行容器:dockerrun--namejiuta-php-apache-7.4-d-p9000:80\-v/mnt/datadisks/docker-root/jiuta/www:/var/www/html\--log-o......
  • vue2.x版本中productionTip=false设置无效
    引用自:https://www.cnblogs.com/javaxubo/p/17397457.html  首先,我们看到vue官网中关于productionTip的API使用:但是,我在本地中使用却无效,代码如下:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatibl......
  • VScode里用MPE插件导出带大纲的HTML和PDF文件
    前置条件:1.在VScode里安装好MarkdownPreviewEnhanced插件2.导出PDF文件,需要用到Prince软件,要先在电脑上安装Prince软件,可以去它的官网下载                Prince-DownloadPrince(princexml.com)windows系统的,选这个就可以了,解压后放在自己想放的......
  • 看不懂来打我,vue3如何将template编译成render函数
    前言在之前的通过debug搞清楚.vue文件怎么变成.js文件文章中我们讲过了vue文件是如何编译成js文件,通过那篇文章我们知道了,template编译为render函数底层就是调用了@vue/compiler-sfc包暴露出来的compileTemplate函数。由于文章篇幅有限,我们没有去深入探索compileTemplate函数是......
  • vue编译器
    ast-编译成代码import*aspathfrom'path'importtype{Plugin,ResolvedConfig}from'vite'import{NodePath}from'@babel/traverse';import{JSXElement}from'@babel/types';import{compile,generate,transform......
  • Vue2和Vue3的区别
    ①双向数据绑定的原理发生变化Vue2利用defineproperty为每个对象的属性添加监听器,当属性发生变化的时候,自动更新对应的DOM元素  Vue3使用proxy代理技术,代替之前的define方式,代理对象data的所有修改工作Proxy的优势①defineProperty只能监听某个属性,不能对全对象监听②......
  • 基于SpringBoot+MySQL+SSM+Vue.js的餐馆订餐系统(附论文)
    演示视频基于SpringBoot+MySQL+SSM+Vue.js的餐馆订餐系统技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描述基于SpringBoot+MySQL+SSM+Vue.js的餐馆订餐系统(附论文),用......
  • ssm基于spring和vue开发的web新闻流媒体平台论文
    摘要如今的时代,是有史以来最好的时代,随着计算机的发展到现在的移动终端的发展,国内目前信息技术已经在世界上遥遥领先,让人们感觉到处于信息大爆炸的社会。信息时代的信息处理肯定不能用之前的手工处理这样的解决方法,必须采用计算机来处理这些信息,因为传统方法对应计算机处......
  • vue 插件 | 自动滚动 vueSeamlessScroll
    1.下载安装npminstallvue-seamless-scroll--save2.引入importvueSeamlessScrollfrom"vue-seamless-scroll";3.注册使用组件<vueSeamlessScroll:class-option='defaultOption':data="activeData"style="height:194px;">......
  • Vue相关原理
    1、VUE2和VUE3对比响应式区别vue2的响应式原理是利⽤es5的⼀个API,Object.defineProperty()对数据进⾏劫持结合发布订阅模式的⽅式来实现的。vue3中使⽤了es6的proxyAPI对数据代理,通过reactive()函数给每⼀个对象都包⼀层Proxy,通过Proxy监听属性的变化,从⽽实现......