虛擬列表
什么是虛擬列表
虛擬列表是一種根據滾動容器元素的可視區域來渲染長列表數據中某一個部分數據的技術
為什么需要虛擬列表
虛擬列表是對長列表的一種優化方案。在前端開發中,會碰到一些不能使用分頁方式來加載列表數據的業務形態,我們稱這種列表叫做長列表。比如,手機端,淘寶商品展示,美團外賣等,數據量特別龐大,不適合分頁,以及懶加載,這時候我們可以采用虛擬列表,只展示可視區域數據。
直接上代碼
HTML
<div>
<div class="list-view" ref="container" @scroll="handleScroll">
<div class="list-view-phantom" ref="clientHeight" :style="{ height: contentHeight + 'px' }"></div>
<ul ref="content" class="list-view-content">
<li class="list-view-item" :style="{ height: itemHeight + 'px' }" :key="index" v-for="(val, index) in list">
{{ val }}
</li>
</ul>
</div>
</div>
js
export default {
name: 'ListView',
computed: {
contentHeight() {
// 計算滾動條高度
return this.data.length * this.itemHeight;
}
},
mounted() {
this.getData();
this.update();
},
data() {
return {
data: [], // 總數據
itemHeight: 30, // 單個高度
list: [], // 渲染數據
};
},
methods: {
update(scrollTop = 0) {
// 獲取當前可展示數量
const count = Math.ceil(this.$el.clientHeight / this.itemHeight);
// 取得可見區域的起始數據索引
const start = Math.floor(scrollTop / this.itemHeight);
// 取得可見區域的結束數據索引
const end = start + count;
// 計算出可見區域對應的數據,讓 Vue.js 更新
this.list = this.data.slice(start, end);
// 把可見區域的 top 設置為起始元素在整個列表中的位置(使用 transform 是為了更好的性能)
this.$refs.content.style.webkitTransform = `translate3d(0, ${ start * this.itemHeight }px, 0)`;
},
handleScroll(e) {
// 獲取當前滾動條滾動位置
const scrollTop = this.$refs.container.scrollTop;
this.update(scrollTop);
},
getData() {
//創建模擬數據
let data = [];
for (let i = 0; i < 1000000; i++) {
data.push(`第 ${i} 個數據`)
}
this.data = [...data];
}
}
}
CSS
.list-view {
width: 400px;
height: 400px;
overflow: auto;
position: relative;
border: 1px solid #c1c1c1;
box-shadow: 3px 3px 5px #ccc;
}
.list-view-phantom {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.list-view-content {
left: 0;
right: 0;
top: 0;
position: relative;
}
.list-view-item {
padding: 6px;
color: #999;
line-height: 30px;
}