窗口事件
scroll 事件
scroll
事件在文档或文档元素滚动时触发,主要出现在用户拖动滚动条。
window.addEventListener('scroll', callback);
该事件会连续地大量触发,所以它的监听函数之中不应该有非常耗费计算的操作。推荐的做法是使用
requestAnimationFrame
或
setTimeout
控制该事件的触发频率,然后可以结合
customEvent
抛出一个新事件。
(function () {
var throttle = function (type, name, obj) {
var obj = obj || window;
var running = false;
var func = function () {
if (running) { return; }
running = true;
requestAnimationFrame(function() {
obj.dispatchEvent(new CustomEvent(name));
running = false;
});
};
obj.addEventListener(type, func);
};
// 将 scroll 事件转为 optimizedScroll 事件
throttle('scroll', 'optimizedScroll');
})();
window.addEventListener('optimizedScroll', function() {
console.log('Resource conscious scroll callback!');
});
上面代码中,
throttle()
函数用于控制事件触发频率,它有一个内部函数
func()
,每次
scroll
事件实际上触发的是这个函数。
func()
函数内部使用
requestAnimationFrame()
方法,保证只有每次页面重绘时(每秒60次),才可能会触发
optimizedScroll
事件,从而实际上将
scroll
事件转换为
optimizedScroll
事件,触发频率被控制在每秒最多60次。
改用
setTimeout()
方法,可以放置更大的时间间隔。
(function() {
window.addEventListener('scroll', scrollThrottler, false);
var scrollTimeout;
function scrollThrottler() {
if (!scrollTimeout) {
scrollTimeout = setTimeout(function () {
scrollTimeout = null;
actualScrollHandler();
}, 66);
}
}
function actualScrollHandler() {
// ...
}
}());
上面代码中,每次
scroll
事件都会执行
scrollThrottler
函数。该函数里面有一个定时器
setTimeout
,每66毫秒触发一次(每秒15次)真正执行的任务
actualScrollHandler
。
下面是一个更一般的
throttle
函数的写法。
function throttle(fn, wait) {
var time = Date.now();
return function() {
if ((time + wait - Date.now()) < 0) {
fn();
time = Date.now();
}
}
}
window.addEventListener('scroll', throttle(callback, 1000));
上面的代码将
scroll
事件的触发频率,限制在一秒一次。
lodash
函数库提供了现成的
throttle
函数,可以直接使用。
window.addEventListener('scroll', _.throttle(callback, 1000));
本书前面介绍过
debounce
的概念,
throttle
与它区别在于,
throttle
是“节流”,确保一段时间内只执行一次,而
debounce
是“防抖”,要连续操作结束后再执行。以网页滚动为例,
debounce
要等到用户停止滚动后才执行,
throttle
则是如果用户一直在滚动网页,那么在滚动过程中还是会执行。
resize 事件
resize
事件在改变浏览器窗口大小时触发,主要发生在
window
对象上面。
var resizeMethod = function () {
if (document.body.clientWidth < 768) {
console.log('移动设备的视口');
}
};
window.addEventListener('resize', resizeMethod, true);
该事件也会连续地大量触发,所以最好像上面的
scroll
事件一样,通过
throttle
函数控制事件触发频率。
fullscreenchange 事件,fullscreenerror 事件
fullscreenchange
事件在进入或退出全屏状态时触发,该事件发生在
document
对象上面。
document.addEventListener('fullscreenchange', function (event) {
console.log(document.fullscreenElement);
});
fullscreenerror
事件在浏览器无法切换到全屏状态时触发。