使用被动事件侦听器加速滚动事件
好的,让我快速解决这个问题。 我 讨厌 将 wheel
(或 touchstart
和 touchmove
)事件附加到页面的网站。 非常讨厌他们。 主要原因是可怕的结果性能,尤其是在移动设备上。 您会看到,浏览器必须等待重新绘制页面,直到事件侦听器完成执行,因为事件可以被取消。 如果您的事件在每一次滚动时都运行,那么滚动页面会变得非常卡顿,尤其是如果您不对事件进行去抖动处理。 幸运的是,现在有一个解决方案:Passive Event Listeners。
被动事件侦听器 允许您将不可取消的处理程序附加到事件,让浏览器围绕您的事件侦听器进行优化。 例如,浏览器可以继续以本机速度滚动,而无需等待事件处理程序完成执行。
虽然它们是规范中相对较新的补充,但它们已经得到 大多数大玩家 的支持。 (基本上除了 IE、Edge 和 Opera Mini 之外的所有人。)
此外,它们的使用不会真正破坏现有行为。 如果需要支持其他浏览器,可以使用这个polyfill。
用法
不幸的是,使用被动事件非常复杂。
假设您的原始代码是这样的:
// Really, if you're using wheel, you should instead be using the 'scroll' event, as it's passive by default. document.addEventListener('wheel', (evt) => { // ... do stuff with evt }, true)
你需要用这个替换它:
document.addEventListener('wheel', (evt) => { // ... do stuff with evt }, { capture: true, passive: true })
是的。 我知道。 几乎不可能绕着你的头。 😉
让我试着解释一下。
因此,通常在注册滚动事件时,您添加最后一个参数 true
,以指示您的事件应该在捕获阶段运行。 (IE。 自上而下而不是自下而上)
启用被动事件的新功能之一是 EventListenerOptions 规范。 听起来很吓人,但它实际上只是可选地将捕获布尔值替换为具有一些属性的对象。 在这种情况下,我们可以将 capture
设置为 true
以获得与第一个示例相同的结果,然后将 passive
设置为 true
以进行事件被动的。
要进一步提高性能,请确保您正在限制或消除事件。 :)
用途
在移动设备上感知到的性能损失最大(比如说快五倍)的事件是 scroll、wheel、touchstart 和 touchmove . 默认情况下,Scroll 已经是被动的,因此可以排除一个事件。 从 Chrome 55 开始,touchstart 和 touchend 也是被动的。
因此,如果您在移动设备上处理这四个事件中的任何一个,那么投入那个微小的 polyfill 并将 { passive: true }
添加到这些事件中并没有什么坏处。 99% o 时间您无论如何都不需要取消这些事件,使用 { passive: true }
可以大幅提升性能。 那为什么不呢?