在做移動端或者其他無限下拉加載時會遇到不斷插入dom的場景,隨着dom的增多頁面會出現卡頓,遇到這種情況開發者會採取一系列的優化措施,比如複用dom等,那麼到底爲什麼會出現卡頓呢?本文將探討這個疑問。
網頁卡頓時,瀏覽器進程內存佔用很大,這就說明在卡頓出現的時候,瀏覽器佔用的內存是很大的,如圖:
一個實例:
<body>
<div id="app"></div>
</body>
<script>
addDom()
addDom()
addDom()
addDom()
addDom()
function addDom(){
let d = document.createDocumentFragment();
for(var i = 0;i<30;i++){
let li = document.createElement('li')
li.addEventListener('click', function(e) {
let _this = e.target;
let dom = e.target.tagName.toLowerCase();
_this.style.color = 'red';
})
li.innerHTML = `</div>
<h4>
測試圖片
</h4>
<img style = "height:20px;width:100px" src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591105123139&di=90a63b4962d0b4405ce65c2096a676c2&imgtype=0&src=http%3A%2F%2Fimg0.imgtn.bdimg.com%2Fit%2Fu%3D3769023270%2C3433174748%26fm%3D214%26gp%3D0.jpg"/>
</div>`
d.appendChild(li)
}
document.getElementById('app').appendChild(d)
}
</script>
一個下拉加載列表,隨着dom的增加, HEAP SNAPSHOTS逐漸加大,如下圖所示:
那麼到底是哪部分佔用內存增加了呢?
從上面可以看出隨着dom的增加 ,HTMLLIElement佔用的內存逐漸增加,這是由於下拉加載過程中在頁面中添加了LI元素。
shallow size和retained size
Shallow Size:
Shallow size就是對象本身佔用內存的大小,不包含其引用的對象。
- 常規對象(非數組)的 Shallow size 由其成員變量的數量和類型決定。
- 數組的shallow size有數組元素的類型(對象類型、基本類型)和數組長度決定。
Retained Size:
對象的Retained Size = 對象本身的Shallow Size + 對象能直接或間接訪問到的對象的Shallow Size
也就是說 Retained Size
就是該對象被 GC(Garbage Collection)
之後所能回收內存的總和。
這裏GC是指垃圾回收,瀏覽器的主流垃圾回收機制時標記清除(ie中存在引用計數清除)。
除了dom節點內存增大,監聽事件佔用的內存也逐漸加大
監聽事件的內存也逐漸增大
隨着內存的佔用增大,到一定程度時,網頁就出現了卡頓。
解決辦法:
1,重複利用dom結構,創建虛擬列表
2,使用事件委託,將監聽事件綁定到父元素上
參考:
https://www.cnblogs.com/yanglongbo/articles/9762359.html
https://blog.csdn.net/strange_monkey/article/details/81746232