jQuery 在滚动上删除/插入 DOM 元素很挑剔
我正在 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();
});
});
总的来说,它运行良好,尤其是当用户向下滚动时。向上滚动也可以,但由于某种原因,它更加挑剔,有时会卡住。向上滚动和向下滚动之间的唯一主要区别是我在内容前面添加而不是附加内容。
那么我的问题是,为什么向上滚动不如向下滚动可靠?有什么想法/猜测/建议吗?
I'm building code for a web view in Appcelerator Titanium. Because of the massive (book length) size of the text on the webpage, I've built some jQuery to automatically remove/insert the page's content as the user scrolls. This means that only a small portion of the page is loaded at any given time, so there is a lot less stress on operating memory and much smoother rendering. Here's the code:
$(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();
});
});
Overall, it's working well, especially when the user scrolls down. Scrolling up also works, but for some reason it's much more finicky, and sometimes it gets stuck. The only major difference between scrolling up and scrolling down is that I'm prepending the content instead of appending it.
My question, then, is why might the upward scrolling be less reliable than the downward? Any thoughts/guesses/suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我最终得到的代码。它运行完美,并且其大小约为原始代码的四分之一。
This is the code I ended up with. It's working perfectly, and it's about a quarter of the size of the original code.
我的猜测如下:
前置需要比附加更多的渲染工作,因为插入元素之后的所有 dom 都应该重建。在附加时插入一个后没有元素
无论如何,如果你只预置/附加一次而不是50次,jquery的工作速度会更快,
你应该重写这个块,为了最大限度地减少预置的数量
我想你没有很多部分,所以你可以做这样的事情
我想你会改变一些东西,以适应你的代码,但这是想法 - >最小化 dom 更改操作的数量,准备一堆元素并将它们全部插入在一起
My guess is following:
prepending requires much more rendering efforts then appending, since all dom that goes after inserted element should be rebuilded. while appending there are no elements after inserted one
Anyway, jquery works MUCH faster if you prepend/append only once and not 50 times
you should rewrite this block, in order to minimize number of prepends
I suppose you dont have many sections, so you can do something like this
i suppose you will change something, to adjust to your code, but this is idea -> minimize number of dom change operations, prepare bunch of elements and insert them alltogether