虛擬列表元件:
template部分:
|-container-監聽滾動事件
|---phantom-繫結資料總高度使得頁面可以滑動
|---list-迴圈item資料更新top距離,使得新資料可展示
<template> <div ref="list" class="virtual-list-container" @scroll="scrollListener($event)" > <div class="virtual-list-phantom" :style="{ height: `${listHeight}px` }" ></div> <div class="virtual-list" :style="{ top: updateTop }"> <div class="virtual-list-item" :style="{ height: `${itemHegith}px` }" v-for="(value, index) in visibleData" :key="index" > <slot :data="value"></slot> </div> </div> </div></template>
script部分:
<script>export default { props: { // 大資料列表 listData: { type: Array, default: () => [], }, // Item高度 itemHegith: { type: Number, default: 30, }, }, computed: { listHeight() { // 總高度 = 總資料 * 每項高度 return this.listData.length * this.getActualHeight(); }, visibleCount() { // 可顯示列表總數 = 顯示高度 / 每項高度 return Math.ceil(this.screenHeight / this.getActualHeight()); }, visibleData() { // 資料切片獲取可視資料 const data = this.listData.slice( this.startIndex, Math.min(this.endIndex, this.listData.length) ); return data; }, updateTop() { // 更新距離頂部的偏移距離,顯示新資料到可視區域 return `${this.startOffset}px`; }, }, data() { return { // 可視區域高度 screenHeight: 500, // 偏移量 startOffset: 0, // 起始元素索引 startIndex: 0, // 終止元素索引 endIndex: 0, }; }, mounted() { // 初始化終止索引 this.endIndex = this.startIndex + this.visibleCount; }, methods: { // 獲取item的實際高度: 由height+padding+border... getActualHeight() { const itemPadding = 10 + 10; const itemBorder = 1; return this.itemHegith + itemPadding + itemBorder; }, // 監聽頁面滾動 scrollListener() { let scrollTop = this.$refs.list.scrollTop; // 更新可視區域資料的條件 // 資料總的高度 - 滾動的距離 >= 可視區域 if (this.listHeight - scrollTop >= this.screenHeight) { // 獲取起止索引 this.startIndex = Math.floor(scrollTop / this.getActualHeight()); this.endIndex = this.startIndex + this.visibleCount; // 獲取偏移距離 this.startOffset = scrollTop - (scrollTop % this.getActualHeight()); } }, },};</script>
style部分:
最新評論