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

Sahel Sharify
Sahel Sharify

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

问题在于,通常轮事件监听器在概念上是被动的(请勿调用 preventDefault()),但并未这样明确指定,这就要求浏览器等待 JS 事件处理完成,然后才能开始滚动/缩放,即使不需要等待也是如此。在 Chrome 56 中,我们针对 touchstarttouchmove 解决了此问题,后来 Safari 和 Firefox 也采用了该变更。正如我们当时制作的演示视频所示,保留原有行为会导致滚动响应出现明显的延迟。现在,在 Chrome 73 中,我们对 wheelmousewheel 事件应用了相同的干预。

干预

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

window.addEventListener("wheel", func);

将等同于:

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

在监听器内调用 preventDefault() 的操作将被忽略,并会显示以下开发者工具警告:

[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() 调用被忽略,因此可能会出现意外滚动/缩放的情况。您的应用可以通过 defaultPrevented 属性检查调用 preventDefault() 是否有任何影响,来确定它是否会实际发生此问题。受影响情况的修复方法相对容易:将 {passive: false} 传递给 addEventListener() 以替换默认行为,并将事件监听器保留为阻塞状态。