airuikun / technology-blog

个人博客,前端技术收集,一起共同学习与成长
3.18k stars 292 forks source link

第 15 题:1000-div问题 #15

Open airuikun opened 5 years ago

airuikun commented 5 years ago
Lanveer commented 5 years ago

var oFrag=document.createDocumentFragment();

for(var i=0;i<1000;i++){ var op=document.createElement("div"); var oText=document.createTextNode(‘i’); op.appendChild(oText); oFrag.appendChild(op); } document.body.appendChild(oFrag);

lvruiyang commented 5 years ago

应该先创建一个div,后续的复制这个元素,避免重复创建元素,再放到元素片段里面 var divFragment=document.createDocumentFragment(); let div=document.createElement("div"); for(var i=0;i<1000;i++){ divFragment.append(div.cloneNode()) } document.body.appendChild(divFragment);

chen4342024 commented 5 years ago

在chrome浏览器上试了下,使用fragment比不用反而更慢点呢..

应该是现代浏览器有针对这方面做优化了。所以,并不需要用 var fragment = document.createDocumentFragment(); fragment.appendChild(elem); 这种方式了吧 ?

mochen666 commented 5 years ago

使用 requestAnimationFrame 分片插入

yexk commented 5 years ago

其实js操作字符串比操作对象高效的多。我觉得这是最高效也是最快的。

let _html = '';
for(var i=0;i<1000;i++){
   _html += '<div></div>';
}
ElementObj.innerHTML= _html;
chen4342024 commented 5 years ago

其实js操作字符串比操作对象高效的多。我觉得这是最高效也是最快的。

let _html = '';
for(var i=0;i<1000;i++){
   _html += '<div></div>';
}
ElementObj.innerHTML= _html;

用代码跑了一遍,实际上并没有比直接插入快 。 我也有点疑惑``

        let loopNum = 5000;
        console.time("handleNormalAppendDiv");
        for (var i = 0; i < loopNum; i++) {
            var op = document.createElement("div");
            containerEl.appendChild(op);
        }
        console.timeEnd("handleNormalAppendDiv");

        console.time("handleStringAppendDiv");
        let html = "";
        for (var i = 0; i < loopNum; i++) {
            html += "<div></div>";
        }
        var op = document.createElement("div");
        op.innerHTML = html;
        containerEl.appendChild(op);
        console.timeEnd("handleStringAppendDiv");

`` 结果输出: handleNormalAppendDiv: 5.595947265625ms handleStringAppendDiv: 6.323974609375ms

yexk commented 5 years ago

其实js操作字符串比操作对象高效的多。我觉得这是最高效也是最快的。

let _html = '';
for(var i=0;i<1000;i++){
   _html += '<div></div>';
}
ElementObj.innerHTML= _html;

用代码跑了一遍,实际上并没有比直接插入快 。 我也有点疑惑``

        let loopNum = 5000;
        console.time("handleNormalAppendDiv");
        for (var i = 0; i < loopNum; i++) {
            var op = document.createElement("div");
            containerEl.appendChild(op);
        }
        console.timeEnd("handleNormalAppendDiv");

        console.time("handleStringAppendDiv");
        let html = "";
        for (var i = 0; i < loopNum; i++) {
            html += "<div></div>";
        }
        var op = document.createElement("div");
        op.innerHTML = html;
        containerEl.appendChild(op);
        console.timeEnd("handleStringAppendDiv");

`` 结果输出: handleNormalAppendDiv: 5.595947265625ms handleStringAppendDiv: 6.323974609375ms

你这个操作不对吧。。你还多了创建了一级dom。时间当然多了。 handleNormalAppendDiv生成应该是dom>dom5000 handleStringAppendDiv生成的应该是dom>dom>dom5000

看我codepen的demo吧。可以证明我是对的。我的结论是 string < fragment < normal (根据耗时排序) https://codepen.io/yexk/pen/KYBKMR 2019-04-22_113720 (ps:多测试几次)

chen4342024 commented 5 years ago

其实js操作字符串比操作对象高效的多。我觉得这是最高效也是最快的。

let _html = '';
for(var i=0;i<1000;i++){
   _html += '<div></div>';
}
ElementObj.innerHTML= _html;

用代码跑了一遍,实际上并没有比直接插入快 。 我也有点疑惑``

        let loopNum = 5000;
        console.time("handleNormalAppendDiv");
        for (var i = 0; i < loopNum; i++) {
            var op = document.createElement("div");
            containerEl.appendChild(op);
        }
        console.timeEnd("handleNormalAppendDiv");

        console.time("handleStringAppendDiv");
        let html = "";
        for (var i = 0; i < loopNum; i++) {
            html += "<div></div>";
        }
        var op = document.createElement("div");
        op.innerHTML = html;
        containerEl.appendChild(op);
        console.timeEnd("handleStringAppendDiv");

`` 结果输出: handleNormalAppendDiv: 5.595947265625ms handleStringAppendDiv: 6.323974609375ms

你这个操作不对吧。。你还多了创建了一级dom。时间当然多了。 handleNormalAppendDiv生成应该是dom>dom_5000 handleStringAppendDiv生成的应该是dom>dom>dom_5000

看我codepen的demo吧。可以证明我是对的。我的结论是 string < fragment < normal (根据耗时排序) https://codepen.io/yexk/pen/KYBKMR 2019-04-22_113720 (ps:多测试几次)

试了几次,string和normal的确会有波动 。 不过,按你截图的结果: 大概率是 string < normal < fragment 。 fragment大概率是耗时最长的呀。而不是排中间

claudewowo commented 5 years ago

感觉这里提到的性能优化, 并不是单单指 dom 渲染耗时, 也包含 dom 回流和重绘, 如果是全部 append 肯定会执行至少 1000次回流甚至还有重绘, 所以 string 和 fragment 应该性能比较好, 但如何检测呢?

wbcs commented 5 years ago
function getDiv(num) {
  return '<div></div>'.repeats(num);
}

function insert(times, container) {
 if (times > 0) {
  let temp = times - 10 > 0 ? times - 10 : times;
  container.innerHTML += getDiv(temp);
 setTimeout(() => {
   insert(times - 10, container);
  }, 200);
 }
}

需要给浏览器间歇时间,这样浏览器会自行对js代码JIT以及对reflow等优化,否则来不及优化。

fariellany commented 4 years ago

在chrome浏览器上试了下,使用fragment比不用反而更慢点呢..

应该是现代浏览器有针对这方面做优化了。所以,并不需要用 var fragment = document.createDocumentFragment(); fragment.appendChild(elem); 这种方式了吧 ?

我测试的也是这样的 两者没太大区别

JaykeyGuo commented 4 years ago

其实js操作字符串比操作对象高效的多。我觉得这是最高效也是最快的。

let _html = '';
for(var i=0;i<1000;i++){
   _html += '<div></div>';
}
ElementObj.innerHTML= _html;

这个方式比操作DOM的成本更低一些