JQuery удаление / вставка элементов DOM на прокрутке является привередливым - PullRequest
0 голосов
/ 21 ноября 2011

Я строю код для веб-представления в Appcelerator Titanium.Из-за огромного (длина книги) размера текста на веб-странице я создал несколько 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();
});

});

В целом, это работает хорошо, особенно когда пользователь прокручивает страницу вниз.Прокрутка вверх также работает, но по какой-то причине она гораздо более привередлива, а иногда застревает.Единственное существенное различие между прокруткой вверх и прокруткой вниз заключается в том, что я добавляю контент вместо его добавления.

Тогда мой вопрос: почему прокрутка вверх может быть менее надежной, чем вниз?Есть мысли / догадки / предложения?

Ответы [ 2 ]

1 голос
/ 21 ноября 2011

Это код, которым я закончил. Он отлично работает и составляет примерно четверть размера исходного кода.

$(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 голосов
/ 21 ноября 2011

Мое предположение следующее:

для добавления требуется гораздо больше усилий по отрисовке, чем для добавления, поскольку все 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);
            }
        }

, вам следует переписать этот блок, чтобысвести к минимуму количество prepends

Я полагаю, у вас нет много разделов, поэтому вы можете сделать что-то вроде этогоидея -> минимизировать количество операций смены dom, подготовить кучу элементов и вставить их целиком

...