同時渲染大量資料優化-虛擬列表
阿新 • • 發佈:2022-03-22
在網頁裡面,在某個可視容器內(某個div)一次性渲染所有資料,其實使用者也只能看見一部分資料,其餘得通過滾動來檢視;
那麼我們可以只渲染可見部分資料,不可見部分資料不渲染,通過上下padding來進行佔位使其可以滾動;
滾動得時候不斷計算可所需展示資料的開始下標和結束下標來擷取可視資料;
<!doctype html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .container { width: 300px; height: 600px; overflow: auto; border: 1px solid; margin: 100px auto; } .item { height: 29px; line-height: 30px; border-bottom: 1px solid #aaa; padding-left: 20px; } </style> </head> <body> <div id="app"> <div class="container" ref="container"> <div class="scroll-wrapper" :style="{'paddingTop':this.paddingTop + 'px','paddingBottom': this.paddingBottom + 'px'}"> <div v-for="(item, index) in datas" :key="index" class="item">{{item}}</div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> <script> new Vue({ el: '#app', data: { list: [],//總數居 startIndex: 0,//可見資料開始下標 endIndex: 60,//可見資料結束下標 paddingTop: 0,//上padding paddingBottom: 0,//下padding allHeight: 0//總高度 }, computed: { // 可見資料 datas() { return this.list.slice(this.startIndex, this.endIndex); }, // 資料總條數 numbers(){ return this.list.length; } }, watch: { list(val) {//根據總資料計算總高度和初始下padding const valLen = val.length; this.allHeight = valLen * 30; this.paddingBottom = this.allHeight - this.datas.length * 30; } }, mounted() { const container = this.$refs.container; // 新增滾動事件 container.addEventListener('scroll', () => {//計算上下padding和資料開始結束下標 const top = container.scrollTop;//獲取滾動高度 this.startIndex = Math.floor(top / 30);//獲取資料開始下標,例如,top為100時,startIndex為3,表示第一二三個資料已經不在可視區域,從第四個開始顯示 this.endIndex = this.startIndex + 60;//資料結束下標 this.paddingTop = top;//滾動距離為上padding // 結束下標大於等於資料個數時表示滑動到了底部,下padding設定為0 if (this.endIndex >= this.numbers) { this.endIndex=this.numbers; this.paddingBottom = 0 return } console.log(this.endIndex) //下padding等於總高度-上padding-可是區域高度 this.paddingBottom = this.allHeight - 600 - this.paddingTop; }) // 新增資料 let arr = new Array(100000).fill(0); arr = arr.map((item, index) => { return index; }) this.list = arr; } }) </script> </body> </html>
原文連結:https://blog.csdn.net/qq_30282133/article/details/112343569