vue 虚拟滚动实现
前言
针对于数据较多的表格,我们一般采用的是跳转按钮实现。若要实现滚动出现更多,除了采用按需加载之外,我们还可以采用此“虚拟滚动”,可进一步减少标签的数量,提高渲染速度。
一、效果实现
从该视频中可见,无论向下滑动多少,右边渲染的标签数量仍是不变的
模拟虚拟表单实现
二、实现思路
1、确定可视区的宽高度,用一个空标签占位本应显示所有数据的区域
<div
id="app"
ref="app"
@scroll="onScroll"
:style="{ '--rowHeight': rowHeight + 'px' }"
>
<div class="scroll-view" ref="scrollView"></div>
<div class="list" ref="list">
<div class="row" v-for="(item, index) in showData" :key="index">
{{ item }}
</div>
</div>
</div>
#app {
position: fixed;
top: 50%;
left: 50%;
width: 500px;
/* height: 500px; */
border: 1px solid blue;
transform: translate(-50%, -50%);
overflow-y: auto;
}
.scroll-view {
/* height: 4000px; */
}
.list {
position: absolute;
top: 0;
left: 0;
}
.row {
height: var(--rowHeight);
}
2、用computed,数组slice截取渲染的数据
computed: {
showData() {
return this.dataList.slice(this.start, this.end);
}
},
3、滑动出多高,就用transform平移回多少,从而保证数据一直再可视区
//滑出高度
const scrollTop = this.$refs.app.scrollTop;
//滑出个数
const rowTopNumber = Math.round(scrollTop / this.rowHeight);
this.$refs.list.style.transform = `translateY(
${scrollTop}px
)`;
this.start = rowTopNumber;
this.end = rowTopNumber + this.showRows;
}
三、代码实现
<template>
<div>
<div
id="app"
ref="app"
@scroll="onScroll"
:style="{ '--rowHeight': rowHeight + 'px' }"
>
<div class="scroll-view" ref="scrollView"></div>
<div class="list" ref="list">
<div class="row" v-for="(item, index) in showData" :key="index">
{{ item }}
</div>
</div>
</div>
</div>
</template>
<script>
const d = new Array(100000).fill(null).map((item, index) => index + 1);
export default {
name: "App",
props: {
//每个块高度
rowHeight: {
type: Number,
default: 30
},
//返回个数
returnData: {
type: Array,
default: () =>
new Array(200000).fill(null).map((item, index) => index + 1)
},
showRows: {
type: Number,
default: 20
}
},
computed: {
showData() {
console.log(this.dataList.slice(this.start, this.end), 333333333333333);
return this.dataList.slice(this.start, this.end);
}
},
data() {
return {
dataList: d,
start: 0,
end: this.showRows
};
},
mounted() {
// 视口动态高度
this.$refs.app.style.height = this.showRows * this.rowHeight + "px";
this.$refs.scrollView.style.height = d.length * this.rowHeight + "px";
},
methods: {
onScroll() {
//滑出高度
const scrollTop = this.$refs.app.scrollTop;
//滑出个数
const rowTopNumber = Math.round(scrollTop / this.rowHeight);
this.$refs.list.style.transform = `translateY(
${scrollTop}px
)`;
this.start = rowTopNumber;
this.end = rowTopNumber + this.showRows;
}
}
};
</script>
<style>
#app {
position: fixed;
top: 50%;
left: 50%;
width: 500px;
/* height: 500px; */
border: 1px solid blue;
transform: translate(-50%, -50%);
overflow-y: auto;
}
.scroll-view {
/* height: 4000px; */
}
.list {
position: absolute;
top: 0;
left: 0;
}
.row {
height: var(--rowHeight);
}
</style>