移動端頁面隨着滑動的dom愈來愈長,會出現卡頓的現象,進而下降用戶體驗,因而可視區渲染方案出來。html
可視區渲染就像一句話說的:敵不動我動,山不就我我就山。dom
可視區渲染原理:ide
1,有個滾動區域,下面的content類,要求overflow:auto,也就是能夠使用滾動;在實際項目開發中這個根據可視區窗口大小變化函數
2,一個足夠高的渲染盒子,下面中viewArea類,其高度等於全部內容條數x單條內容高度,在實際項目中這個會受限於手機html的最大高度限制ui
3,可視區顯示的內容條數viewArea類裏面的內容,內容多少能夠經過pageSize控制orm
4,經過監聽滾動事件,觸發可視區內容更新,包括更新呈現的內容以及更新內容的位置,後者實際上是人爲製造了一種滾動效果htm
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>無限滾動中的虛擬列表(只渲染可視區域,dom元素可複用)</title> <meta name="viewport" content="initial-scale=1.0"> <meta name="format-detection" content="telephone=no, email=no"> </head> <body> <header> <!-- <h1>無限滾動中的虛擬列表-防抖和節流(只渲染可視區域,dom元素可複用)</h1> --> <h1>無限滾動中的虛擬列表(只渲染可視區域,dom元素可複用)</h1> </header> </article> <article class="d-part d-effect"> <style> .container { height: 600px; overflow: auto; } .item { min-height: 60px; border-bottom: 1px solid #cccccc; border-top: 1px solid #cccccc; width: 100%; text-align: center; background-color: darkgray; /* padding: 30px 0; box-sizing: border-box; */ } </style> <div class="container"> <div class="content"> <div class="viewArea"> <div class="item">0</div> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> </div> </div> </div> <script> var item = document.querySelector('.viewArea .item'); //須要渲染的單個列表元素 var container = document.querySelector('.container'); //可視區域元素盒子 console.log(item); var start = 0; // 開始位置 var pageSize = 10; // 每頁展現的數據 var total = 100000; //數據總長度 // var itemHeight = 61; // 每一個item的高度 var itemStyle = getComputedStyle(item); // 獲取元素最終樣式 var itemHeight = Number(itemStyle.height.split('px')[0]) + Number(itemStyle.borderTopWidth.split('px')[0]) + Number(itemStyle.borderBottomWidth.split('px')[0]); // 每一個item的高度 console.log('itemHeight', itemHeight); // 設置數據列表的總高度 document.querySelector('.container .content').style.height = itemHeight * total + 'px'; updateDom(start, pageSize, 0); //更新渲染列表的高度和數據 function updateDom(start, pageSize, height) { document.querySelector('.container .content .viewArea').style.transform = 'translateY(' + height + 'px)'; let all = document.querySelectorAll('.viewArea .item'); // 獲取全部渲染列表 for (var i = start, itemIndex = 0, len = start + pageSize; i < len; i++, itemIndex++) { all[itemIndex].innerHTML = i; } } // 滾動處理函數 function handleScroller() { var lastStart = 0; // 上次開始的位置 return () => { var currentScrollTop = container.scrollTop; var fixedScrollTop = currentScrollTop - currentScrollTop % itemHeight; // currentScrollTop % itemHeight這個是爲了讓滾動效果更天然 console.log(currentScrollTop, currentScrollTop % itemHeight) var start = Math.floor(currentScrollTop / itemHeight); if (lastStart !== start) { // 這塊避免一些重複性渲染,這樣也不用計算方向了 lastStart = start; updateDom(start, pageSize, fixedScrollTop); } } } document.querySelector('.container').addEventListener('scroll', handleScroller(), false); </script> </article> </div> </body> </html>