虚拟列表,实际上就是在首屏加载的时候,只加载可视区域内需要的列表项,当滚动发生时,动态通过计算获得可视区域内的列表项,并将非可视区域内存在的列表项删除。该技术是解决渲染大量数据的一种解决方法。
实现虚拟列表,需要获取以下几个属性
- 可视区域起始数据索引(startIndex)
- 可视区域结束数据索引(endIndex)
- 计算可视区域数据,并渲染到页面中
- 计算startIndex对应的数据在整个列表中的偏移位置listTop并设置到列表上
高度固定
令App组件(父组件)产生一万条虚拟数据来模拟接口,在List组件中实现对应的功能
App组件:
<template>
<div>
<List :items="items" :size="60" :shownumber="10"></List>
</div>
</template>
<script>
import List from '@/List.vue'
export default {
components: {
List
},
computed: {
// 模拟数据
items() {
return Array(10000).fill('').map((item, index) => ({
id: index,
content: index
}))
}
}
};
</script>
<style scoped></style>
List组件:
<template>
<div class="container" :style="{ height: containerHeight }" @scroll="handleScroll" ref="container">
<!-- 数据列表 -->
<div class="list" :style="{top:listTop}">
<!-- 列表项 -->
<div v-for="item in showData" :key="item.id" :style="{height:size+'px'}">
{{ item.content }}
</div>
<!-- 用于撑开高度的元素 -->
<div class="bar" :style="{height:barHeight}"></div>
</div>
</div>
</template>
<script>
export default {
name: 'List',
props:{
// 要渲染的数据
items:{
type:Array,
required:true
},
// 每条数据渲染节点的高度
size:{
type:Number,
required:true
},
// 每次渲染DOM节点个数
shownumber:{
type:Number,
required:true
}
},
data(){
return{
start:0, //要展示数据的其实下标
end:this.shownumber //结束下标
}
},
computed:{
// 最终展示数据
showData(){
return this.items.slice(this.start,this.end)
},
// 容器的高度
containerHeight(){
return this.size * this.shownumber + 'px'
},
// 撑开容器内部高度的元素的高度
barHeight(){
return this.size * this.items.length + 'px'
},
// 列表项上滚动改变top的值
listTop(){
return this.start * this.size + 'px'
},
},
methods:{
// 容器滚动事件
handleScroll(){
// 获取容器顶部滚动的尺寸
const scrollTop = this.$refs.container.scrollTop
this.start = Math.floor(scrollTop / this.size)
this.end = this.start + this.shownumber
}
}
};
</script>
<style scoped>
.container{
overflow-y: scroll;
background-color: rgb(150,150,150,.5);
font-size: 20px;
font-weight: bold;
line-height: 60px;
width: 500px;
margin: 0 auto;
position: relative;
text-align: center;
}
.list{
position: absolute;
top: 0;
width: 100%;
}
</style>
这样可以实现一个简单的固定高度的虚拟列表功能。
1万+

被折叠的 条评论
为什么被折叠?



