使用被动事件侦听器加速滚动事件

来自菜鸟教程
跳转至:导航、​搜索

好的,让我快速解决这个问题。 我 讨厌wheel(或 touchstarttouchmove)事件附加到页面的网站。 非常讨厌他们。 主要原因是可怕的结果性能,尤其是在移动设备上。 您会看到,浏览器必须等待重新绘制页面,直到事件侦听器完成执行,因为事件可以被取消。 如果您的事件在每一次滚动时都运行,那么滚动页面会变得非常卡顿,尤其是如果您不对事件进行去抖动处理。 幸运的是,现在有一个解决方案: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 以进行事件被动的。

要进一步提高性能,请确保您正在限制或消除事件。 :)

用途

在移动设备上感知到的性能损失最大(比如说快五倍)的事件是 scrollwheeltouchstarttouchmove . 默认情况下,Scroll 已经是被动的,因此可以排除一个事件。 从 Chrome 55 开始,touchstarttouchend 也是被动的。

因此,如果您在移动设备上处理这四个事件中的任何一个,那么投入那个微小的 polyfill 并将 { passive: true } 添加到这些事件中并没有什么坏处。 99% o 时间您无论如何都不需要取消这些事件,使用 { passive: true } 可以大幅提升性能。 那为什么不呢?