2011-11-21 68 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