虚拟列表
// 实现思路,在scroll事件中,每次计算出当前的开始位置(this.scrollTop / this.itemHeight)
和结束位置,计算出现在所处的位置,在用css绝对定位。
<template>
<div
ref="contentBox"
class="content-box"
:style="{ height: contentHeight + 'px' }"
@scroll="scrollListener"
>
<div
:style="{
position: 'relative',
height: showBoxHeight
}"
>
<div
:style="{
position: 'absolute',
top: top + 'px'
}"
>
<div
class="box-item"
:style="{
height: itemHeight + 'px',
lineHeight: itemHeight + 'px'
}"
v-for="(item, index) of showList"
:key="index"
>
{{ item }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'virtualList',
data() {
return {
total: 1000000, //模拟数据总数
contentHeight: 400,
showList: [],
list: [],
startIndex: 0,
endIndex: null,
itemHeight: 30,
scrollTop: 0, //卷起高度
showNum: 10, //当前显示列表个数
top: 0 //距离顶部距离
}
},
computed: {
showBoxHeight() {
return this.itemHeight * this.list.length + 'px'
}
},
mounted() {
this.getList()
this.scrollListener()
},
methods: {
getList() {
// 构造虚拟数据
this.list = Array.from({ length: this.total }).map(
(_, index) => `第${index + 1}条数据`
)
},
scrollListener() {
this.scrollTop = this.$refs.contentBox.scrollTop // 获取距离顶部距离
// this.showNum = Math.ceil(this.contentHeight / this.itemHeight) // 可展示个数
this.startIndex = Math.floor(this.scrollTop / this.itemHeight) // 起点位置
this.endIndex = this.startIndex + 10 // 结束位置
this.showList = this.list.slice(this.startIndex, this.endIndex) // 当前查看数据
this.top = this.startIndex * this.itemHeight // 距离顶部的距离,控制内容出现在可视区域
}
}
}
</script>
<style scoped>
.content-box {
margin: 30px auto 0;
position: relative;
width: 400px;
border: 1px solid #e4e7ed;
overflow-y: auto;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
border-radius: 4px;
padding: 10px 0;
}
.box-item {
padding: 0 32px 0 20px;
color: #606266;
}
.content-box::-webkit-scrollbar {
width: 10px;
height: 1px;
}
.content-box::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #e5e5e5;
}
.content-box::-webkit-scrollbar-track {
border-radius: 10px;
background: #ffffff;
}
</style>