搜尋

首頁  >  問答  >  主體

javascript - 當一次取得數千個資料時如何渲染DOM?

//方法一:长度为l的数组切成n片,追加n次
$('.btn1').click(function(event) {
    var arr=['中国','美国','法国','英国','俄罗斯','朝鲜','瑞典','挪威','德国','意大利','南非','埃及','巴基斯坦','哈萨克斯坦','印度','越南','加拿大','澳大利亚'];
    var result=[];
    for(i=0;i<arr.length;i=i+3){
      result.push(arr.slice(i,i+3));
    }
    for(j=0;j<result.length;j++){
        var html='';
        for(k=0;k<result[j].length;k++){
            html+='<li>'+result[j][k]+'</li>';
        }
        console.log('html--'+html);
        $('.list').append(html);
    }
});

//方法二:长度为l的数组直接追加到dom中,循环l次
$('.btn2').click(function(event) {
    var arr=['中国','美国','法国','英国','俄罗斯','朝鲜','瑞典','挪威','德国','意大利','南非','埃及','巴基斯坦','哈萨克斯坦','印度','越南','加拿大','澳大利亚'];
    var html='';
    for(i=0;i<arr.length;i++){
      html+='<li>'+arr[i]+'</li>';
    }
    $('.list').append(html);
});

這是firebug測出來的時間:8.3毫秒是分組追加的(方法一),5.74毫秒是直接追加的(方法二)

個人覺得分組會減輕dom渲染,避免卡頓,但firebug測出來的跟我的想法相反,是不是資料太小的原因呢?

PHP中文网PHP中文网2786 天前735

全部回覆(5)我來回復

  • 阿神

    阿神2017-05-19 10:34:30

    你的分組其實沒有真真的起到分擔壓力,需要加入定時器,用分時函數

    一個範例是建立 WebQQ 的 QQ 好友清單。清單中通常會有成百上千個好友,如果一個好友
    用一個節點來表示,當我們在頁面中渲染這個清單的時候,可能要一次往頁面中建立成百上千
    個節點。
    在短時間內往頁面中大量添加 DOM 節點顯然也會讓瀏覽器吃不消,我們看到的結果往往就
    是瀏覽器的卡頓甚至假死。程式碼如下:

    var ary = [];
    for ( var i = 1; i <= 1000; i++ ){
        ary.push( i ); // 假设 ary 装载了 1000 个好友的数据
    };
    var renderFriendList = function( data ){
        for ( var i = 0, l = data.length; i < l; i++ ){
            var p = document.createElement( 'p' );
            p.innerHTML = i;
            document.body.appendChild( p );
        }
    };
    renderFriendList( ary );
    

    這個問題的解決方案之一是下面的 timeChunk 函數, timeChunk 函數讓創建節點的工作分批進
    行,例如把 1 秒鐘創建 1000 個節點,改為每隔 200 毫秒創建 8 個節點。

    // data 数据  func 插入操作  interval 时间周期  该周期插入的项目数
    var timeChunk = function(data, func, interval, count){
        var obj, timer;
        
        var start = function(){
            for(var i = 0; i < Math.min(count || 1, data.length); i++){
                obj = data.shift();
                func(obj);
            }
        };
        
        return function(){
            timer = setInterval(function(){
                if(data.length === 0){
                    return clearInterval(timer);
                }
                
                start();
            }, interval);
        };
    }
    
    
    var data= [];
    for ( var i = 1; i <= 1000; i++ ){
        data.push( i );
    };
    
    renderFriendList = timeChunk(data, function(n){
        var p = document.createElement( 'p' );
        p.innerHTML = n;
        document.body.appendChild( p );
    }, 200, 10);
    
    renderFriendList();

    以上摘自設計模式一書

    回覆
    0
  • 高洛峰

    高洛峰2017-05-19 10:34:30

    你的方案一慢的原因有以下幾點,
    $('.list').append(html);
    這段程式碼每循環一次,需要重新去定位dom元素即$('.list')jquery需要去取得.list這個文檔,相當於
    循環N就得去定位N次,這當然效率低了,所以你的方案二隻是定位了一次就把元素全部追加進去了效率明顯高咯,
    至於你的陣列分片,在js裡面完全體現不出來吧,該循環幾次還是幾次,反而沒提高效率,還多加了一步分片,js本身就是單線程的,再怎麼分效率還是一樣,

    回覆
    0
  • 阿神

    阿神2017-05-19 10:34:30

    一次取得幾千條數據,表示你這個api設計的有問題。

    回覆
    0
  • 習慣沉默

    習慣沉默2017-05-19 10:34:30

    個人覺得第一種更消耗記憶體和時間(在量少的時候),一是,上面的語句加起來,運行的次數多,二是分多次append肯定不如一次性append

    回覆
    0
  • 淡淡烟草味

    淡淡烟草味2017-05-19 10:34:30

    一次獲的幾千條數據,也不會全都一次性append的。

    合理的做法是按顯示的重要性和次要性去加載。首先載入能看到的,然後在進程空閒的時候分批將剩下的插入頁面中。

    回覆
    0
  • 取消回覆