在默认情况下使滚轮快速滚动

Sahel Sharify
Sahel Sharify

为了提高 wheel 滚动/缩放性能,建议开发者通过将 {passive: true} 选项传递给 addEventListener(),将 wheelmousewheel 事件监听器注册为被动。将事件监听器注册为被动会告知浏览器,滚轮监听器不会调用 preventDefault(),并且浏览器可以安全地执行滚动和缩放,而不会阻塞监听器。

问题在于,大多数情况下,滚轮事件监听器在概念上是被动的(不会调用 preventDefault()),但并未明确指定为被动,因此浏览器需要等待 JS 事件处理完成,然后才能开始滚动/缩放,即使不需要等待也是如此。在 Chrome 56 中,我们修复了 touchstarttouchmove 存在的这个问题,后来 Safari 和 Firefox 也采用了这一更改。如您在当时制作的演示视频中所看到的,如果不对此行为进行更改,滚动响应会出现明显延迟。现在,在 Chrome 73 中,我们对 wheelmousewheel 事件应用了相同的干预措施。

干预措施

此项更改的目标是缩短用户开始通过滚轮或触控板滚动后更新显示屏所需的时间,而无需开发者更改代码。我们的指标显示,在根目标(窗口、文档或正文)上注册的 75% 的 wheelmousewheel 事件监听器未为“passive”选项指定任何值,并且超过 98% 的此类监听器未调用 preventDefault()。在 Chrome 73 中,我们将默认将在根目标(窗口、文档或正文)上注册的 wheelmousewheel 监听器设为被动监听器。这意味着,事件监听器(例如):

window.addEventListener("wheel", func);

等效于:

window.addEventListener("wheel", func, {passive: true});

并且系统会忽略在监听器内调用 preventDefault(),并显示以下 DevTools 警告:

[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312

中断和指南

在大多数情况下,不会出现任何中断。只有在极少数情况下(根据我们的指标,不到 0.3% 的网页),由于默认被视为被动监听器的监听器内会忽略 preventDefault() 调用,才可能会发生意外滚动/缩放。您的应用可以通过检查调用 preventDefault() 是否通过 defaultPrevented 属性产生了任何影响,来确定它是否可能会在实际环境中遇到此问题。受影响情形的修复相对简单:将 {passive: false} 传递给 addEventListener() 以替换默认行为,并将事件监听器保留为阻塞状态。