测试应用documentFragment 和 直接操作dom 的区别

假装没事ソ 提交于 2020-04-06 03:50:28

DocumentFragment 节点不属于文档树,继承的 parentNode 属性总是 null。

不过它有一种特殊的行为,该行为使得它非常有用,即当请求把一个 DocumentFragment 节点插入文档树时,插入的不是 DocumentFragment 自身,而是它的所有子孙节点。这使得 DocumentFragment 成了有用的占位符,暂时存放那些一次插入文档的节点。它还有利于实现文档的剪切、复制和粘贴操作

同时我们了解到当需要对页面DOM进行操作的时候必然会导致多次 重绘、回流(什么是重绘,回流?)。这样会加大页面的负担。影响页面性能。因此我们可以创建这样一个临时占位符。

测试 demo:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <div id="box">
        <button onclick="addList()">Button</button>
        <button onclick="addList2()">Button</button>
    </div>
    <div>
        <ul id="myList">
            <li>item</li>
        </ul>
        <hr>
    </div>
<script type="text/javascript">

function addList(){
    
    var doc = document,
    list = doc.getElementById('myList'),
    item,
    i;
    console.time('addList');
    for(i=0; i<1000; i++){
        item = doc.createElement('li');
        list.appendChild(item);
        item.appendChild(doc.createTextNode('item '+ i));
        console.log(list.clientHeight);
    }
    console.timeEnd('addList');
}


function addList2(){
    
    var doc = document,
    list = doc.getElementById('myList'),
    fragment = doc.createDocumentFragment(),
    item,
    i;
    console.time('addList2');
    for(i=0; i<1000; i++){
        item = doc.createElement('li');
        item.appendChild(doc.createTextNode('item '+ i));
        fragment.appendChild(item);
        console.log(list.clientHeight);
    }
    list.appendChild(fragment);
    console.timeEnd('addList2');
}

</script>

</body>
</html>

 

借用 在知乎上 网友 付星昱 的评论 解释一下:

直接往元素里 append的操作会引发 reflow,在循环中多次触发 reflow是非常不讨好的事情,
我们聪明的现代浏览器会将短时间内的多次 reflow收集起来组成队列,在一定时间后 flush队列,将多个 reflow的变为一次 reflow。

直接获取 offsetHeight会导致浏览器马上 flush队列,计算出当前值。
除了计算 offsetHeight,clientHeight/clientWidth,offsetWidth,scrollTop/Left/Height/width也会使浏览器立即 flush队列。

 

可以理解为什么  我之前多次测试 而看到的 两种方式 在时间上没什么差异的原因了;

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!