setTimeout(() => { // 插入十萬條數據 const total = 100000; // 一次插入的數據 const once = 20; // 插入數據需要的次數 const loopCount = Math.ceil(total / once); let countOfRender = 0; const ul = document.querySelector('ul'); // 添加數據的方法 function add() { const fragment = document.createDocumentFragment(); for(let i = 0; i < once; i++) { const li = document.createElement('li'); li.innerText = Math.floor(Math.random() * total); fragment.appendChild(li); } ul.appendChild(fragment); countOfRender += 1; loop(); } function loop() { if(countOfRender < loopCount) { window.requestAnimationFrame(add); } } loop(); }, 0)
原理:渲染大數據時,合理使用createDocumentFragment和requestAnimationFrame,將操作切分為一小段一小段執行。
documentFragment:
是一個虛擬的Dom列表,可以儲存待處理的xml片段(el元素),因為他不在真實的Dom結構中,所以對它所做的操作不會觸發瀏覽器的回流,只會在他插入dom的時候觸發一次而已。
上面把多個動態生成的div插入到了虛擬節點里,在最后完成之后只做了一次插入,這樣就只會觸發一次回流。
但是在數量太多的時候,哪怕是一次插入,也會因為瀏覽器渲染不過來導致失去響應,這時候就需要增加一定的時間間隔,可以使用setTimeout,也可以使用一個api------requestAnimationFrame
requestAnimationFrame()
1.方法是為了動畫 專門使用的api,在通常的動畫中會定義一個定時器來幾秒幾秒的發生變化,但是為了性能和更加方便,它提供了這個可以在1秒鍾運行大約60次(≈16.7ms)回調的api。
而且會把這一刻所有的dom操作緩存起來,在一次回流重繪中完成操作,它的每次調用並不是指定時間的,而是跟緊瀏覽器的刷新頻率,所以可以做到:在瀏覽器的刷新頻率時進行回流,保證性能效率。
當頁面不是激活狀態的情況下,這個函數將會停止回調,進行暫停來節省cpu操作。激活時再繼續。
在元素隱藏時不會進行重繪回流。
2.它的返回值為一個long的標識符,和settimeout一樣,可以調用cancelAnimationFrame()傳入這個標識符來取消這個回調。
使用這個可以在瀏覽器下一次’刷新’的時候運行指定的回調,在這里來插入這多個節點。
使用這樣可以大批量插入很多數據 頁面也不會失去響應卡住,可以保證比較好的性能