jQuery在scroll上删除/插入DOM元素很挑剔

jQuery在scroll上删除/插入DOM元素很挑剔,jquery,webview,appcelerator,Jquery,Webview,Appcelerator,我正在Appcelerator Titanium中构建web视图的代码。由于网页上文本的巨大(书籍长度),我构建了一些jQuery,可以在用户滚动时自动删除/插入页面内容。这意味着在任何给定的时间都只加载页面的一小部分,因此操作内存的压力小得多,渲染也更平滑。代码如下: $(document).ready(function() { // assign content index and parent, add to array var content = new Array();

我正在Appcelerator Titanium中构建web视图的代码。由于网页上文本的巨大(书籍长度),我构建了一些jQuery,可以在用户滚动时自动删除/插入页面内容。这意味着在任何给定的时间都只加载页面的一小部分,因此操作内存的压力小得多,渲染也更平滑。代码如下:

$(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();
});

});
$(文档).ready(函数(){
//分配内容索引和父级,添加到数组
var content=新数组();
var指数=0;
$('section>*')。每个(函数(){
//设置变量
var标记=$(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();
//添加到html
$(this.attr('parent',parent).attr('index',index);
//添加到数组
内容[索引]=新数组(标记、id、样式、索引、父项、html);
//下一个索引
索引++;
});
//查找中心元素,删除元素
var midW=parseInt($(窗口).width()/2);
var midH=parseInt($(窗口).height()/2);
var centerEl=document.elementFromPoint(中间、中间);
if(!$(centerEl.attr('parent')){
centerEl=$(centerEl.parent();
}
centerEl=parseInt($(centerEl.attr('index'));
$('section>*')。删除();
//插入内容
var firstEl=中心线-30;
if(firstEl<0){
firstEl=0;
}
var lastEl=中心线+30;
if(lastEl>content.length){
lastEl=content.length;
}
for(var i=firstEl;i*').css('background-color','white');//删除
$('section>*[index='+centerEl+']')。css('background-color','aqua');//删除
//计算要显示的内容
var firstEl=中心线-30;
if(firstEl<0){
firstEl=0;
}
var lastEl=中心线+30;
if(lastEl>content.length){
lastEl=content.length;
}
//删除元素
$('section>*')。每个(函数(){
var index=$(this.attr('index');
如果(索引lastEl){
$(this.remove();
}
});
//添加元素
如果(更改>0){
for(var i=firstEl;i=firstEl;i--){
如果($('section>*[index='+i+']')。长度==0){
var tag=含量[i][0];
var id=含量[i][1];
var style=内容[i][2];
var指数=含量[i][3];
var parent=含量[i][4];
var html=内容[i][5];
var el=''+html+'';
$('section[index='+parent+']')。前置字符(el);
}
}
}
}
}
$(窗口)。滚动(函数(){
loadContent();
});
});
总的来说,它工作得很好,尤其是当用户向下滚动时。向上滚动也可以,但由于某些原因,它更挑剔,有时会卡住。向上滚动和向下滚动之间唯一的主要区别是,我是在预先添加内容,而不是附加内容

那么,我的问题是,为什么向上滚动比向下滚动更不可靠?有什么想法/猜测/建议吗?

我的猜测如下:

由于插入元素之后的所有dom都应该重建,所以预结束需要比追加更多的渲染工作。追加时,插入一个元素后没有任何元素

无论如何,如果只预加/追加一次,而不是50次,jquery的运行速度会快得多

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);
            }
        }

我想你会改变一些东西,以适应你的代码,但这是idea->最小化dom更改操作的数量,准备一堆元素并将它们全部插入到一起

这就是我最终得到的代码。它工作得很好,大约是原始代码的四分之一大小

$(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();
    });

});
$(文档).ready(函数(){
//分配节ID
var-sectionID=0;
$('section')。每个(函数(){
$(this.attr('id','s'+sectionID);
sectionID++;
});
//分配元素ID,添加到数组
var content=新数组();
var-contentID=0;
$('section>*')。每个(函数(){
$(this.attr('id',contentID);
content[contentID]=新数组($(this).parent('section').attr('id'),$(this));
contentID++;
});
//显示元素
变量显示=函数(){
//确定中心
var center=parseInt($(document.elementFromPoint(parseInt($(window.width()/2)、parseInt($(window.height()/2))).closest('section>*').attr('id');
//确定第一个/最后一个
var第一,最后;
如果(!isNaN(中间)){
第一个=((中心-20)<0)?0:(中心-20);
last=((中心+20)>content.length)?content.length:(中心+20);
}
//隐藏
$(
$(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();
    });

});