在做移动端或者其他无限下拉加载时会遇到不断插入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