描述:滚动列表数据量庞大的时候(如一万条数据),会在页面创建一万个DOM元素,而页面的DOM太多会对页面的渲染造成很大的负担,出现页面卡顿等情况,严重的减少用户体验感,所以需要使用虚拟滚动列表,对长列表功能模块进行优化。
在head中导入vue
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
css
* {
margin: 0;
padding: 0;
}
.container {
width: 280px;
height: 500px;
margin: 50px auto;
border: 1px solid #ccc;
overflow: auto;
}
.contentBox {
position: relative;
}
.cell {
position: absolute;
left: 0;
line-height: 25px;
}
html
<div id="app">
<div class="container">
<div class="contentBox">
<p class="cell" v-for="(item, index) in showList" :key="index" :style="{top: item.top}">{{item.data}}</p>
</div>
</div>
</div>
js
window.onload = function () {
var vue = new Vue({
el: '#app',
data: {
// 全部数据量
list: new Array(10000).fill(0).map((item, index) => ('内容' + (index + 1))),
// 展示的数据
showList: [
{ data: '暂无数据', top: 0 }
],
// 每行高度
cellHeight: 0,
// 可视框显示的数据量
showCount: 0
},
methods: {
// 初始化基本参数
initData() {
let containerDom = document.querySelector('.container')
let contentBoxDom = document.querySelector('.container .contentBox')
let cell = document.querySelector('.cell')
// 盒子高度
let containerDomHeight = containerDom.clientHeight
// 每行高度
this.cellHeight = cell.clientHeight
// 可视框需要显示的数据量
this.showCount = Math.ceil(containerDomHeight / this.cellHeight)
// 滚动盒子的高度
contentBoxDom.style.height = this.cellHeight * this.list.length + 'px'
// 实现虚拟滚动
this.initScrolLoad(containerDom)
containerDom.onscroll = () => {
this.initScrolLoad(containerDom)
}
},
// 实现虚拟滚动
initScrolLoad(containerDom) {
// 滚动出去的距离
let scrollTop = containerDom.scrollTop
// 可视区域第一行索引(-2: 往上多渲染两条数据)
let startIndex = Math.floor(scrollTop / this.cellHeight) - 2
// 可视区域最后一行索引(+4: 往下多渲染两条数据(要算上上面的-2))
let endIndex = startIndex + this.showCount + 4
// 获取需要渲染的数据
this.showList = []
for (let i = startIndex; i < endIndex; i++) {
this.showList.push({
data: this.list[i],
// 算好每个元素需要的top值
top: i * this.cellHeight + 'px'
})
}
// console.log(startIndex, endIndex)
},
},
mounted() {
this.initData()
}
})
}
如列表项高度不固定,可使用虚拟滚动列表(动态高)
版权声明:本文为weixin_47551643原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。