如何让vue长列表快速加载
目录
- 背景
- 主要内容
- 一、组件对比
- 二、实现思路
- 三、关键方法源码分析
- 四、使用方式
- 五、参数说明
- 总结
vue-long-list-load,满足特殊条件的长列表加载。支持:1、各个节点高度不同且可自由设定 2、各个节点可修改不影响加载效果 3、可精确的滚动到指定位置。
背景
有个长列表渲染的需求,本来用vue-virtual-scroll-list的。但是每个节点的高度不一样,用着有点问题。如果也有相应的需求可以参考下我的方案。欢迎大家交流!
vue-long-list-load
满足特殊条件的的长列表加载。 列表内各个节点高度不一,各个节点可以进行修改,定位到指定位置指定节点。 www.npmjs.com/package/vue…
主要内容
- vue-long-list-load 与 vue-virtual-scroll-list 对比
- vue-long-list-load实现思路
- 基本代码
- 插件使用方式
- 插件参数说明
一、组件对比
vue-long-list-load ,vue-virtual-scroll-list两个插件各有优缺点,当我们在选择插件的时候要选择最适合应用场景的插件。下面是两个插件的基本功能对比。vue-long-list-load 主要特点是适用于各个节点尺寸不统一的场景,vue-virtual-scroll-list更适用于高度统一节点以列表长度以w计的这种列表。
组件 | vue-long-list-load | vue-virtual-scroll-list |
---|---|---|
npm地址 | www.npmjs.com/package/vue… | www.npmjs.com/package/vue… |
核心 | 先空dom占位,显示区域内组件挂载显示 | 计算当前显示区域内要显示的组件挂载 |
横向 | 支持 | 支持 |
列表内高度一致 | 支持 | 支持 |
列表内高度不一致 | 支持 | 支持不好 |
滚动到指定组件 | 支持 | 高度不一致时计算不准确 |
滚动事件 | 支持 | 支持 |
组件高度改变事件 | 支持 | 支持 |
隐藏组件 | 支持 | 不支持 |
二、实现思路
主要思想就是通过\color{ red} { 虚拟dom} 虚拟dom占位各个节点,根据可显示视口的变化来展示该展示的节点。影响可显示视口的因素的监听,页面整体宽高变化、节点高度变化、页面的滚动定位到某一个节点等都可能会影响到视口的变化。当视口发生变化后计算可显示的节点,将可显示的节点挂载上节点的组件,不在视口内的节点销毁组件紧保留一个空的div。下图为实现思路的流程图。
三、关键方法源码分析
主入口htML结构如下,\color{ red} { v-for} v−for 展示长列表长度的的节点,并且通过:style 来设置一个\color{ red} { 最小高度} 最小高度,设置最小高度的原因是这个高度值可能不准确,当真正组件渲染完之后计算出最准确的高度,如果直接height的话可能会使节点内的组件展示不全。同时每个节点设置唯一id(scrollITem_ 唯一标识),在根据数据获取dom信息时候使用。节点组件定义了唯一的class (long-item- 唯一标识),主要用来挂载真实列表组件,同时监听组件的高度变化。showList[index]来控制节点是否时候显示的唯一标识。
!--html代码--> template> div : :style="{ 'min-height': (item.height> =0?item.height:height) + 'px'} " :key="item[dataKey]" :id="'scrollItem_' + item[dataKey]" v-for="(item,index) in dataList" > long-item v-if="showList[index]" :dataKey="dataKey" :item="item" :boxHeight="item.height||0" :direction="direction" :heightChange="heightChange" :extendCcomments="extendCcomments"> /long-item> /div> /template>
当showList[index]为true的时候,对应的节点显示。long-item 在mounted生命周期时,回调extendCcomments。通过\color{ red} { Vue.extend PRofile} Vue.extendProfile挂载到对应的dom上。componentProps是节点组件传过来的一些参数,在挂载的时候全部挂载上。
!--挂载组件--> extendCcomments(item){ this.COMponentProps.item=item VAR Profile = Vue.extend(this.dataComponent); // 创建 Profile 实例,并挂载到一个元素上 new Profile({ propsdata:this.componentProps } ).$mount('.long-item-'+item[this.dataKey]); }
通过\color{ red} { element-resize-detector} element−resize−detector来监听dom尺寸的变化,每个节点的宽高发生变化的时候,并且与原来的尺寸不一样回调heightChange方法,进行尺寸的更新及显示节点的操作计算。
!--每个节点尺寸发生变化--> this.$nextTick(()=> { this.$DomListener.listenTo(document.getElementById('long-item-'+this.item[this.dataKey]), (element)=> { if(this.boxHeight != element[this.directionconfig.width]){ this.heightChange(this.item, element[this.directionConfig.width]) } } ) } );
获取可显示的视口区域的方法,页面滚动和尺寸变化都会调用到这个方法,所以这个方法在调用的时候做防抖处理300ms内有连续调用只会执行最后一次调用,要不然会频繁计算影响性能。可显示视口区域计算方式是当前视口 及 前后两个视口总共三个视口的尺寸。这样在小的滚动范围内会有较好的体验。
getShowLimit(startTop) { const scrollTop = startTop || this.scrollWrap[this.directionConfig.scrollTo] || 0; // 滚动距离 this.viewClientHeight = this.scrollWrap[this.directionConfig.width]; // 可视区域高度 this.scrollTop = scrollTop this.showStart = scrollTop - this.viewClientHeight this.showEnd = scrollTop + 2*this.viewClientHeight if(this.setTopTimer){ clearTimeout(this.setTopTimer) } this.setTopTimer = setTimeout(() => { this.setItemTopheight() } , 300); } ,
根据高度或者宽度来计算节点是否显示,因为这个计算量比较大避免而且这个方法与其他方法没有什么关联,直接单独开一个\color{ red} { 独立线程} 独立线程进行计算。通过引入\color{ red} { simple-web-worker} simple−web−worker这个插件单独开一个线程进行计算显示节点。计算方法主要有三点:当前节点的开头在显示视口内、当前节点的结尾在显示视口内、当前节点开头和结尾都不在显示视口内。分为这三种情况,只要满足一种情况,则该节点就显示在显示视口中。
// 根据高度计算节点是否显示 setItemTopheight(){ let stsartId = this.dataList[0]& & this.dataList[0][this.dataKey] let startDom = stsartId & & document.getElementById('scrollItem_'+stsartId) let startTop = startDom ? startDom[this.directionConfig.offset] : 0 this.worker = this.$worker.run((dataList,showStart,showEnd, startTop,hideIds,dataKey,height) => { let topHeight = startTop; // 题目顶部距离顶部距离 let bottomHeight = 0; // 题目底部距离顶部距离 let showList = [] for(let i=0,len=dataList.length; ilen; i++){ let item = dataList[i] if(hideIds.indexOf(item[dataKey]) != -1){ showList[i] = false; continue; } bottomHeight = topHeight + (item.height> =0?item.height:height) // 判断 1.题目顶部在显示范围内 2.题目底部在显示范围内 3.题目顶部和底部都不在显示范围内 if((topHeight> =showStart & & topHeight=showEnd)|| (bottomHeight> =showStart & & bottomHeight=showEnd)|| (topHeightshowStart & & bottomHeight> showEnd) ){ showList[i] = true} else{ showList[i] = false } topHeight += ((item.height> =0?item.height:height)); } return showList } , [this.dataList, this.showStart, this.showEnd, startTop, this.hideIds,this.dataKey,this.height]) .then(res => { this.showList = res } ) this.worker = null } ,
四、使用方式
安装vue-long-list-load:
npm install vue-long-list-load --save
项目内调用
long-list ref="vueLongList" dataKey='id' scrollWrap :dataList="dataList" :dataComponent="dataComponent" :componentProps="componentProps" height=100 > /long-list>
五、参数说明
参数 | 说明 | 类型 | 必填 | 可选值 | 默认值 |
---|---|---|---|---|---|
scrollWrapId | 列表滚动容器id | string | true | — | — |
dataKey | 节点数据内唯一键值 | String | true | — | — |
dataList | 列表数据 | Array | true | 具体见下方说明 | — |
dataComponent | 自定义的节点组件 | — | true | — | — |
ref | 调用组件内部方法 | string | false | — | — |
direction | 滚动方向 | Number | false | 0:纵向,1横向 | 0 |
hideIds | 列表中需要隐藏的节点 | Array | false | 具体见下方说明 | [] |
height | 节点高度 | Number | false | — | 100 |
componentProps | 节点组件要传递的参数 | Object | false | — | { } |
scroll | 滚动区域内滚动回调方法 | Function | false | - | — |
resized | 某个节点宽高发生变化回调方法 | Function | false | 具体见下方说明 |
部分参数说明
& lt; --假设 dataKey=id--> & lt; --列表中需要隐藏的节点--> hideIds:[1, 2] & lt; --列表数据 dataList 内 height 为 **Number**。--> dataList:[ { id:1,height:100} , { id:2,height:200} , { id:3,height:300} , { id:4,height:300} , { id:5,height:300} ] & lt; --节点高度--> height:100 & lt; --如果dataList的数据内有height值 不需要设置这个height--> & lt; --如果dataList 和 height 都不传递的话,默认为100 可能滚动略有卡顿;--> & lt; --建议在每个高度都不相同的时候通过dataList传递,都相同时候通过height传递--> & lt; --某个节点宽高发生变化回调方法 返回参数为id 与高度--> resized(id, height){ }
总结
项目中实践数据,基本每个节点至少500个dom节点,平均也在800个dom节点以上,用vue-long-list-load 不在渲染区域内的题目只会渲染2个dom节点。按正常800左右个dom节点的题目计算 一般渲染区域渲染的节点在9个左右,如果是n节点的列表 ,每次加载 dom操作都减少(n-9)x(800-2)个dom的渲染,如果\color{ red} { 1000个节点} 1000个节点的列表每次加载和操作的时候相当于减少了\color{ red} { 726180} 726180个dom节点的渲染。首次渲染还有修改后的重绘都大大减少了dom的渲染加快了加载速度提高了用户体验。 此方案已经在项目中实践一段时间,用户反馈很好。如果大家也有类似的场景需求,欢迎大家使用!交流!
以上就是如何让vue长列表快速加载的详细内容,更多关于vue 长列表快速加载的资料请关注其它相关文章!
@H_733_406@您可能感兴趣的文章:- Vue实现一个无限加载列表功能
- Vue 列表页带参数进详情页的操作(router-link)
- vue 公共列表选择组件,引用Vant-UI的样式方式
- vue实现前端列表多条件筛选
- vue实现点击按钮“查看详情”弹窗展示详情列表操作
- 关于vue的列表图片选中打钩操作
- vue-列表下详情的展开与折叠案例
- vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
- vue实现循环滚动列表
- vue实现列表滚动的过渡动画
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 如何让vue长列表快速加载
本文地址: https://pptw.com/jishu/594986.html