基础环境
- Vue 2.6
- ant-design-vue
- lodash
具体实现
最外层区域
- 设置外层div固定高度height=300px;
- 监听滚动事件handleScroll,handleScroll函数进行节流处理(
防抖比作等电梯,节流比作过红绿灯;防抖执行最后一个,节流执行第一个)
- 垂直方向可滚动
<template>
<a-spin tip="loading" :spinning="loading">
<div class="outer-box" @scroll="handleScroll" :style="{height: height.toString + 'px'}">
<div>
</a-spin>
</template>
<script>
export default {
data() {
return {
height: 300,
page: 1
}
}
}
</script>
<style scoped>
.outer-box {
border: 1px solid #ddd;
overflow-y: auto;
}
</style>
中间区域
- 增加一个中间区域,高度设置为总的行数(totalNum=1000) * 行高(itemHeight=30px),该区域的作用是
解决“滚动条抖动”的问题
<template>
<a-spin tip="loading" :spinning="loading">
<div class="outer-box" @scroll="handleScroll" :style="{height: height.toString + 'px'}">
<div :style="height: (itemHeight * item.totalNum).toString() + 'px'">
</div>
<div>
</a-spin>
</template>
<script>
export default {
data() {
return {
height: 300,
itemHeight: 30,
totalNum: 0,
data: []
}
},
created() {
this.getData()
},
methods: {
getData() {
const mockData = []
for (i=this.data.length; i<50; i++) {
mockData.push({
id: i.toString(),
text: i.toString() + 'aaaa'
})
}
this.data = Array.prototype.concat(this.data, mockData)
this.totalNum = 1000
}
}
}
</script>
<style scoped>
.outer-box {
border: 1px solid #ddd;
overflow-y: auto;
}
</style>
最内部区域
- 遍历数组data
- 设置每一项的高度为itemHeight(30px)
<template>
<a-spin tip="loading" :spinning="loading">
<div
class="outer-box"
@scroll="handleScroll"
:style="{height: height.toString + 'px'}"
>
<div :style="{height: (itemHeight * item.totalNum).toString() + 'px'}">
<div
v-for="item in data"
:key="item.id"
:style="{height: itemHeight.toString() + 'px'}"
>
{{ item.text }}
</div>
</div>
<div>
</a-spin>
</template>
<script>
export default {
data() {
return {
height: 300,
itemHeight: 30,
totalNum: 0,
data: []
}
},
created() {
this.getData()
},
methods: {
getData() {
const mockData = []
for (i=this.data.length; i<50; i++) {
mockData.push({
id: i.toString(),
text: i.toString() + 'aaaa'
})
}
this.data = Array.prototype.concat(this.data, mockData)
this.totalNum = 1000
}
}
}
</script>
<style scoped>
.outer-box {
border: 1px solid #ddd;
overflow-y: auto;
}
</style>
完善handleScroll
import throttle from 'lodash/throttle
export default {
methods: {
handleScroll: throttle((e) => {
if (this.data.length >= this.totalNum) return
let { scrollTop } = e.target
if (scrollTop + 2 * this.height >= this.totalNum * this.itemHeight) {
this.page += 1
this.getData()
}
}, 100)
}
}