首页IT科技vue 渲染html字符串(uniapp/vue虚拟列表,数据列表渲染优化)

vue 渲染html字符串(uniapp/vue虚拟列表,数据列表渲染优化)

时间2025-05-01 22:19:23分类IT科技浏览5024
导读:引言 相信大家经常会遇到展示一堆数据的需求,几十条数据还好,要是几百上千条,甚至带上了图片。那就会卡得不行。这时候就需要...

引言

相信大家经常会遇到展示一堆数据的需求             ,几十条数据还好                   ,要是几百上千条      ,甚至带上了图片             。那就会卡得不行                   。这时候就需要按需加载      。

按需加载有懒加载虚拟列表             。

懒加载:通过JS滚动或触底触发事件来加载更多的数据       ,类似分页                   。 虚拟列表:只加载可视区域的数据                   ,通过计算长度区间反推需要加载的数据来实现假滑动      。

二者异同

很明显            ,懒加载虽然也有优化       ,可是当用户疯狂下拉刷新时候最后还是会卡                    ,虽然很难有那种场景       。懒加载的好处就是            ,用户往回刷时候因为加载过,所以看上面的内容会比较顺滑                   。

虚拟列表则是只加载可视范围的数据                    ,需要精确计算                   ,若不精确计算也可,但是有些数据会只显示了一部分(这个就需要个人自己优化一下计算的算法了             ,符合需求就可)                   ,而且因为是假滑动      ,所以观感有可能没有懒加载这么好             。

两者在数据请求时             ,可以一次性拿完                   ,也可分次拿取      ,懒加载便是下滑加载或触底时候请求新数据加到旧数据里       。但虚拟列表拿的时候需要参考懒加载       ,因为用户也有往上滑的需求                   ,这算法你们不想累死自己和后端吧                   。

接下来用Uniapp来演示            ,原生vue也可参考使用(更方便)       ,理论上是一样的                    ,区别就在于uniapp做微信小程序时候没有document可供使用(除非使用dhtml-weixin等插件)            ,非H5端在某些组件上不能使用ref获取实例(如view),如此一来操作dom                    ,只能通过官方提供的uni.createSelectorQuery()接口             。

原理

 如图                   ,黑框是数据列表的总高度,红框是你设定的可视范围             ,与动图里不同的是                   ,红框内的数据是实时生成的(并不是通过隐藏其他数据)      ,并且因为偏移量采用了取余操作(如果有需要可以自己定制)             ,保证了在红框内第一条数据永远是完整展示的。只是因为滑动时未停下                   ,js未响应前      ,新的列表不会生成       ,就会有一个假滑动的效果                   。

代码

<template> <scroll-view class="container" scroll-y="true" @scroll="scroll" > <!-- 虚拟列表总高度 --> <view :style="{height: `${totalHeight}rpx`, position: relative}"> <!-- 可视渲染区 --> <view :style="{top: `${top}px`}" style="width: 100%;position:absolute"> <!--在这里自定义你数据的展示结构和样式,itemHeight为这里的总高度--> <view v-for="(item,index) in showList" :key="index" class="item"> <span>我是第{{item.index}}条数据</span> </view> </view> </view> </scroll-view> </template> <script> export default { data(){ return{ allList:[],//原始数据列表 //虚拟列表 showList: [], //可视区域显示的数据 itemHeight: 100,//每条数据所占高度 showNum: 0, //可视区域显示的最大条数 top: 0, //偏移量 scrollTop: 0, //卷起的高度 startIndex: 0, //可视区域第一条数据的索引 endIndex: 0, //可视区域最后一条数据的索引+1                   , } }, onLoad() { //获取数据列表 for(let i=0;i<100;i++){ this.allList.push({index:i}) } // console.log(this.allList) }, onShow() { //第一次时调用一下,且uni.createSelectorQuery()需要在生命周期mounted之后使用 this.scroll() }, computed: { totalHeight() { return this.allList.length*this.itemHeight*2//因为rpx和px的关系 } }, methods:{ //虚拟列表 getShowList(){ //可视区域能出现的数据条数 this.showNum = Math.ceil(this.contentHeight/this.itemHeight); // console.log(可视数量,this.showNum) //可视区域第一条数据的索引 this.startIndex = Math.floor(this.scrollTop/this.itemHeight); // console.log(初始索引,this.startIndex) //可视区域最后一条数据的下一条数据 this.endIndex = this.startIndex + this.showNum; //可视区数据            ,会比实际可视多渲染一条 this.showList = this.allList.slice(this.startIndex, this.endIndex) // console.log(this.showList) //保证滑动时第一条数据完整展示 let offsetY = this.scrollTop - (this.scrollTop % this.itemHeight); this.top = offsetY; }, scroll(){ // 利用uniapp提供的接口获取可视区域的高度和滚动高度 let query=uni.createSelectorQuery() let container=query.select(.container); container.fields({ // rect:true, //是否返回节点布局位置信息{left,top,right,bottom} size:true, //是否返回节点尺寸信息{width       ,height} scrollOffset:true //是否返回节点滚动信息{scrollLeft,scrollTop} },(res)=>{ console.log(res) this.scrollTop=res.scrollTop this.contentHeight=res.height this.getShowList();//因为所在函数是异步 }).exec() }, } } </script> <style> .container{ width: 100%; height: 100vh; /*原生一定得有这个overflow的hidden效果,此处用了scroll-view所以不需要*/ /*overflow:auto;*/ } .item{ /* 按照实际需求写css */ width: 100%; height: 200rpx;/* 要对应上itemHeight */ border: 1rpx solid slateblue; } </style>

注意点

1             、uniapp里需要使用scroll-view才能实现隐藏滑动效果                   。原生的看代码里一样加上overflow:auto即可滑动                    ,原生把所有view结构换成div。

2                   、uni.createSelectorQuery()的那个获取信息成功后执行的函数是异步执行的            ,所以需要留意一下你的同步操作,比如this.getShowList()不要放在外面             。

3      、可惜的是                    ,不知道是不是v-for里的.item的问题                   ,uni.createSelectorQuery()死活都拿不到节点,否则可以动态拿到每个数据节点的实际总高度                   。(注意这里不适用每条数据高度都不一样的情况             ,如需要高度不一样                   ,请自行调整      ,如把itemHeight单独放在list的对象内之类             ,或通过改变现有结构统一固定每条数据的高度

所以我这里uniapp是写死了itemHeigh                   ,itemHeigh(px单位制)和下面css样式里的height需要对应上      ,你也可以看到我computed里让itemHeigh乘了2       ,(因为大多数设备的rpx和px的css像素比例都是2:1)其实对应不上                   ,效果还是会有的            ,所以不用特别纠结代码里的rpx和px单位      。只要渲染的列表数据长度大于可视区域的列表数据长度即可             。

先写到这了       ,有想起来或者出错再补充修改                    ,如果你有更好的建议或纠错            ,欢迎评论,多多点赞谢谢                   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
如何用u盘装win7系统教程图解(三分钟U极速轻松实现用U盘装Win7系统的教程你见过吗) 基于注意力机制的CNN-LSTM预测(深度学习中的注意力机制模型及代码实现(SE Attention、CBAM Attention))