一般来说,您应该避免在由scroll 事件触发的回调中执行任何操作,因为回调将针对窗口滚动的每个像素执行。但是,根据您正在构建的应用程序,在该回调中根本无法避免某些事情。
在滚动回调中执行大量“昂贵”的操作或查询可能会完全冻结浏览器并使您的应用程序无法使用,因此您必须非常小心并谨慎执行。
以下是一些良好做法的示例。
一般示例:
现场示例:http://jsfiddle.net/tfjyf0a3/
// Since we can get away with querying the elements outside of the callback
// our application will be a lot snappier because we're doing less work for
// every scrolled pixel. Always query DOM elements outside if possible.
var $output = $('#output');
var $window = $(window);
// This function is executed for every scrolled pixel, so we need to
// avoid doing "expensive" queries or changing the DOM in here too.
function changeFontSize(scrollNumber) {
// Setting the fontSize here is unavoidable because our application needs it.
$output.css('fontSize', scrollNumber <= 50 ? 18 : Math.floor(scrollNumber/10));
}
$window.on('scroll', function() {
// Since `$(this)` here would be the window object, it's better to
// just use the previous reference named `$window`.
// Querying the scrolled position here is unavoidable because our
// application needs it.
var currentScroll = $window.scrollTop();
// Saving a reference of the `scrollTop()` value is better when
// we need to re-use its value.
$output.html(currentScroll + 'px');
// We have to be cautious inside this function as well.
changeFontSize(currentScroll);
});
// This is a good practice when you need to guarantee the execution of the function
// when there isn't enough content in the body to cause a scrollbar in the Browser.
//
// The 'scroll' event will fire only when there is a scrollbar in the Browser.
$window.scroll();
有时您需要在滚动的回调函数中执行“昂贵的”DOM 操作、查询甚至 Ajax 请求。例如,想象构建一个实现称为无限加载的模式的应用程序。在此应用程序中,当用户通过快速或慢速滚动接近页面底部时,您需要执行以下操作:
- 检查用户是否滚动到底部。
- 检查是否有更多资源要加载。
- 加载资源。
- 将新资源附加到 DOM。
您绝对不想对每个滚动像素执行上述所有步骤。对于这种情况,一个非常好的做法是延迟上述步骤。一个示例可能如下所示:
延迟执行:
现场示例:http://jsfiddle.net/35qb1b88/
var $output = $('#output');
var $window = $(window);
var timer;
function changeFontSize(scrollNumber) {
$output.css('fontSize', scrollNumber <= 50 ? 18 : Math.floor(scrollNumber/10));
// ...
// load resources
// append in DOM
// ...etc
}
function scrollHandler() {
var currentScroll = $window.scrollTop();
$output.html(currentScroll + 'px');
changeFontSize(currentScroll);
}
// This callback will be executed for every pixel but it will
// do nothing if we're scrolling too fast because we're clearing
// the timeout. Only when scrolling has stopped and at least 100
// milliseconds have passed will the `scrollHandler` function run.
$window.on('scroll', function() {
timer && window.clearTimeout(timer);
timer = window.setTimeout(scrollHandler, 100);
});
$window.scroll();
同样的原则也适用于resize 事件。