2011-11-21 83 views
0

我在Appcelerator Titanium中構建web視圖的代碼。由於網頁上的文本大量(書的長度),我已經構建了一些jQuery,以便在用戶滾動時自動刪除/插入頁面的內容。這意味着在任何給定的時間只有一小部分頁面被加載,所以對於操作內存的壓力要小得多,而且渲染更平滑。這裏是代碼:jQuery在滾動條上刪除/插入DOM元素是finicky

$(document).ready(function() { 

// assign content index and parent, add to array 

    var content = new Array(); 
    var index = 0; 
    $('section > *').each(function() { 
     // set variables 
     var tag = $(this).get(0).tagName; 
     var id = $(this).get(0).id; 
     var style = $(this).get(0).className; 
     var parent = $(this).parent('section').attr('index'); 
     var html = $(this).html(); 
     // add to html 
     $(this).attr('parent', parent).attr('index', index); 
     // add to array 
     content[index] = new Array(tag, id, style, index, parent, html); 
     // next index 
     index++; 
    }); 

// find center element, remove elements 

    var midW = parseInt($(window).width()/2); 
    var midH = parseInt($(window).height()/2); 
    var centerEl = document.elementFromPoint(midW, midH); 
    if (!$(centerEl).attr('parent')) { 
     centerEl = $(centerEl).parent(); 
    } 
    centerEl = parseInt($(centerEl).attr('index')); 
    $('section > *').remove(); 

// insert content 

    var firstEl = centerEl - 30; 
    if (firstEl < 0) { 
     firstEl = 0; 
    } 
    var lastEl = centerEl + 30; 
    if (lastEl > content.length) { 
     lastEl = content.length; 
    } 
    for (var i = firstEl; i < lastEl; i++) { 
     var tag = content[i][0]; 
     var id = content[i][1]; 
     var style = content[i][2]; 
     var index = content[i][3]; 
     var parent = content[i][4]; 
     var html = content[i][5]; 
     var el = '<' + tag + ' id="' + id + '" class="' + style + '" index="' + index + '" parent="' + parent + '">' + html + '</' + tag + '>'; 
     $('section[index=' + parent + ']').append(el); 
    } 

// on scroll 

var change; 
var loadContent = function() { 
    // find new center element 
    midW = parseInt($(window).width()/2); 
    midH = parseInt($(window).height()/2); 
    newCenterEl = document.elementFromPoint(midW, midH); 
    if (!$(newCenterEl).attr('parent')) { 
     newCenterEl = $(newCenterEl).parent(); 
    } 
    newCenterEl = parseInt($(newCenterEl).attr('index')); 
    // if the center element has changed 
    if (newCenterEl != centerEl) { 
     // set center 
     if (!isNaN(newCenterEl)) { 
      change = newCenterEl - centerEl; 
      centerEl = newCenterEl; 
     } 
     $('section > *').css('background-color', 'white'); // delete 
     $('section > *[index=' + centerEl + ']').css('background-color', 'aqua'); // delete 
     // calculate what to display 
     var firstEl = centerEl - 30; 
     if (firstEl < 0) { 
      firstEl = 0; 
     } 
     var lastEl = centerEl + 30; 
     if (lastEl > content.length) { 
      lastEl = content.length; 
     } 
     // remove elements 
     $('section > *').each(function() { 
      var index = $(this).attr('index'); 
      if (index < firstEl || index > lastEl) { 
       $(this).remove(); 
      } 
     }); 
     // add elements 
     if (change > 0) { 
      for (var i = firstEl; i <= lastEl; i++) { 
       if ($('section > *[index=' + i + ']').length == 0) { 
        var tag = content[i][0]; 
        var id = content[i][1]; 
        var style = content[i][2]; 
        var index = content[i][3]; 
        var parent = content[i][4]; 
        var html = content[i][5]; 
        var el = '<' + tag + ' id="' + id + '" class="' + style + '" index="' + index + '" parent="' + parent + '">' + html + '</' + tag + '>'; 
        $('section[index=' + parent + ']').append(el); 
       } 
      } 
     } 
     if (change < 0) { 
      for (var i = lastEl; i >= firstEl; i--) { 
       if ($('section > *[index=' + i + ']').length == 0) { 
        var tag = content[i][0]; 
        var id = content[i][1]; 
        var style = content[i][2]; 
        var index = content[i][3]; 
        var parent = content[i][4]; 
        var html = content[i][5]; 
        var el = '<' + tag + ' id="' + id + '" class="' + style + '" index="' + index + '" parent="' + parent + '">' + html + '</' + tag + '>'; 
        $('section[index=' + parent + ']').prepend(el); 
       } 
      } 
     } 
    } 
} 
$(window).scroll(function() { 
    loadContent(); 
}); 

}); 

總的來說,它運行良好,尤其是當用戶滾動下來。向上滾動也可以,但由於某種原因,它更挑剔,有時會卡住。滾動和向下滾動的唯一主要區別在於我預先添加了內容而不是追加內容。

那麼我的問題就是爲什麼向上捲動比向下可靠性低?任何想法/猜測/建議?

+0

就在我發佈這個之後,我試着在每個方向上加載50個元素後面和30個前面,而不是30個。加載額外的元素似乎解決了向上滾動的挑剔性質。我仍然不確定這會是什麼原因,所以如果任何人有洞察力,我會很感激,但至少現在它工作得很順利。 :) – fubeca

回答

1

這是我結束的代碼。它的工作完美,大約是原始代碼大小的四分之一。

$(document).ready(function() { 

// assign section IDs 
    var sectionID = 0; 
    $('section').each(function() { 
     $(this).attr('id', 's' + sectionID); 
     sectionID++; 
    }); 

// assign element IDs, add to array 
    var content = new Array(); 
    var contentID = 0; 
    $('section > *').each(function() { 
     $(this).attr('id', contentID); 
     content[contentID] = new Array($(this).parent('section').attr('id'), $(this)); 
     contentID++; 
    }); 

// display elements 
    var display = function() { 
     // determine center 
     var center = parseInt($(document.elementFromPoint(parseInt($(window).width()/2), parseInt($(window).height()/2))).closest('section > *').attr('id')); 
     // determine first/last 
     var first, last; 
     if (!isNaN(center)) { 
      first = ((center - 20) < 0) ? 0 : (center - 20); 
      last = ((center + 20) > content.length) ? content.length : (center + 20); 
     } 
     // hide 
     $('section > *').each(function() { 
      var id = $(this).attr('id'); 
      if (id < first || id > last) { 
       $(this).remove(); 
      } 
     }); 
     // show 
     var start = $('section > *').first().attr('id') - 1; 
     for (var i = start; i >= first; i--) { 
      $('section#' + content[i][0]).prepend(content[i][1]); 
     } 
     var end = parseInt($('section > *').last().attr('id')) + 1; 
     for (var i = end; i <= last; i++) { 
      $('section#' + content[i][0]).append(content[i][1]); 
     } 
    } 

// listeners 
    $(window).load(function() { 
     display(); 
    }); 
    $(window).scroll(function() { 
     display(); 
    }); 

}); 
0

我的猜測是以下幾點:

預謀需要更多的渲染力度再追加,因爲這走後插入的元素應該rebuilded所有DOM。而附加有沒有插入一個

後反正元素,jQuery的工作得更快,如果你在前面加上/追加只有一次,而不是50倍

for (var i = lastEl; i >= firstEl; i--) { 
      if ($('section > *[index=' + i + ']').length == 0) { 
       var tag = content[i][0]; 
       var id = content[i][1]; 
       var style = content[i][2]; 
       var index = content[i][3]; 
       var parent = content[i][4]; 
       var html = content[i][5]; 
       var el = '<' + tag + ' id="' + id + '" class="' + style + '" index="' + index + '" parent="' + parent + '">' + html + '</' + tag + '>'; 
       $('section[index=' + parent + ']').prepend(el); 
      } 
     } 

你應該重寫該塊,以儘量減少預規劃的數

我想你沒有很多的部分,所以你可以做這樣的事情

var sections={}; 
{ //your loop starts here 

    if (typeof sections[parent]=='undefined'){ 
     sections[parent]=[]; 
    } 
    var el=all+your+stuff; 
    sections[parent].push(el); 

}//ends here 
$(sections).each(function(parent,section){ 
    $('section[index=' + parent + ']').prepend(section);  
}); 

我想你會改變一些東西,到adju st到你的代碼,但這是主意 - >最小化dom更改操作的數量,準備一堆元素並將它們全部插入到一起

+0

這是一個很好的建議,謝謝。我實現了它,它確實提高了性能。然後我意識到我可以認真壓縮我的代碼並通過使用下面添加的代碼來減少DOM更改。 – fubeca