我正在寻找一种有效的方法来不断选择可见窗口/视口中的最后一个元素。
到目前为止,这是我的代码:
$(window).scroll(function () {
$('.post-content p').removeClass("temp last")
$('.post-content p').filter(":onScreen").addClass("temp")
$(".temp").eq(-1).addClass("last")
});
正如您可能想象的那样,这会占用大量资源并且表现不佳。有人可以从更优雅的代码建议吗?
我对Javascript的了解非常基础,所以请耐心等待我。谢谢。
PS:我在onScreen选择器上使用onScreen插件:http://benpickles.github.com/onScreen/
答案 0 :(得分:1)
将函数绑定到滚动事件can lead to serious performance problems。滚动事件在页面滚动时非常激烈地触发,因此将具有大量资源代码的函数绑定到它是一个坏主意。
John建议设置间隔,从而让代码仅在滚动事件后执行一段时间。
<强> Have a look at this jsfiddle to see difference between the implementations 强>
间接处理程序解决方案的代价是滚动和执行代码之间存在明显的延迟,如果您可以为快速执行执行交易,那么您的决定就是您的决定。请务必在您支持的每个浏览器上测试性能。
您可以使用许多不同的概念来加速代码。关于你的代码,它归结为:
所以我提出的是 a Jsfiddle with an example how you could do you scroll handler 。它与您的DOM不完全匹配,因为我不知道您的HTML,但它应该很容易与您的实现相匹配。
与your code相比,我设法将使用的时间减少了95%。您可以通过在chrome中分析两个样本来亲眼看到。
我假设您只想选择最后一个元素,而您不需要临时类
// Store the offsets in an array
var offsets = [];
// Cache the elements to select
var elements = $('.elem');
// Cache the window jQuery Object
var jWindow = $(window);
// Cache the calculation of the window height
var jWindowHeight = jWindow.height();
// set up the variable for the current selected offset
var currentOffset;
// set up the variable for the current scrollOffset
var scrollOffset;
// set up the variable for scrolled, set it to true to be able to assign at
// the beginning
var scrolled = true;
// function to assign the different elements offsets,
// they don't change on scroll
var assignOffsets = function() {
elements.each(function() {
offsets.push({
offsetTop: $(this).offset().top,
height: $(this).height(),
element: $(this)
});
});
};
// execute the function once. Exectue it again if you added
// or removed elements
assignOffsets();
// function to assign a class to the last element
var assignLast = function() {
// only execute it if the user scrolled
if (scrolled) {
// assigning false to scrolled to prevent execution until the user
// scrolled again
scrolled = false;
// assign the scrolloffset
scrollOffset = jWindowHeight + jWindow.scrollTop();
// only execute the function if no current offset is set,
// or the user scrolled down or up enough for another element to be
// the last
if (!currentOffset || currentOffset.offsetTop < scrollOffset || currentOffset.offsetTop + currentOffset.height > scrollOffset) {
// Iterate starting from the bottom
// change this to positive iteration if the elements count below
// the fold is higher than above the fold
for (var i = offsets.length - 1; i >= 0; i--) {
// if the element is above the fold, reassign the current
// element
if (offsets[i].offsetTop + offsets[i].height < (scrollOffset)) {
currentOffset && (currentOffset.element.removeClass('last'));
currentOffset = offsets[i];
currentOffset.element.addClass('last');
// no further iteration needed and we can break;
break;
}
}
return true;
} else {
return false;
}
}
}
assignLast();
// reassign the window height on resize;
jWindow.on('resize', function() {
jWindowHeight = jWindow.height();
});
// scroll handler only doing assignment of scrolled variable to true
jWindow.scroll(function() {
scrolled = true;
});
// set the interval for the handler
setInterval(assignLast, 250);
// assigning the classes for the first time
assignLast();