当 document.hidden 为 true 时,Chrome 中不会触发滚动事件。任何解决方法?
Posted
技术标签:
【中文标题】当 document.hidden 为 true 时,Chrome 中不会触发滚动事件。任何解决方法?【英文标题】:Scroll event not fired in Chrome when document.hidden is true. Any workarounds? 【发布时间】:2021-02-16 14:56:56 【问题描述】:当页面隐藏时,Chrome 永远不会触发滚动事件,尽管页面实际上正在滚动。这看起来像是他们为减少不可见页面的 CPU 和网络使用而实施的。
有没有办法解决这种行为,即使使用 Chrome 的标志或扩展程序?我需要触发“滚动”事件,因为这是我正在测试的。
setInterval(() =>
window.scrollBy(0, 100);
// scrolls indefinitely even when the page is hidden
, 1000);
addEventListener("scroll", () =>
console.log("scroll " + document.documentElement.scrollTop);
// however, this gets fired only if document.hidden is false
);
【问题讨论】:
【参考方案1】:这其实是符合规范的。
滚动事件将作为事件循环的update the rendering 步骤的一部分触发。此更新渲染可以是其步骤 2 到 5 的捷径,当浏览器认为渲染无用时(例如,当文档被隐藏时),浏览器可以随意丢弃它。
所以即使滚动确实发生了,由于渲染还没有发生,所以没有要触发的事件。
注意:在 Firefox 中添加对 requestAnimationFrame
的调用将强制事件触发几秒钟,但很快它们会显示 Chrome 限制所有 rAF 调用,直到文档再次可见。
解决方法取决于您的具体情况。
如果您可以像示例中那样控制滚动的来源,那么自己触发它非常简单,甚至不需要事件。
setInterval(() =>
window.scrollBy(0, 100);
console.log("scroll " + document.documentElement.scrollTop);
, 1000);
:root height: 100000vh
如果你不负责那个原始的setInterval
,但知道它的频率,你也可以并行开始你自己的间隔:
setInterval(() =>
window.scrollBy(0, 100);
, 1000);
setInterval(() =>
console.log("scroll " + document.documentElement.scrollTop);
, 1000);
:root height: 100000vh
如果您不确定它是如何触发的,您可以覆盖所有滚动方法和设置器,以便它们也执行您的回调。
// here we overwrite only scrollBy
const orig = window.scrollBy;
window.scrollBy = function(...args)
orig.call(this, ...args);
console.log("scroll " + document.documentElement.scrollTop);
;
setInterval(() =>
window.scrollBy(0, 100);
, 1000);
:root height: 100000vh
如果您仍然需要确定是否确实发生了用户滚动,您可以通过仅在 document.hidden
为 true 时调用回调来调整所有这些变通方法,并让 scroll
事件处理其他事件。
PS:如果您担心平滑滚动,请注意浏览器不会在文档隐藏时更新平滑滚动位置。
【讨论】:
谢谢。我很难强制触发滚动事件。我尝试覆盖可见性 api、document.hidden 等的吸气剂。没有运气。事实上,即使我自己触发了 document.hidden 为 true 的事件,也有些事情不太奏效。 我不确定你的意思。您不需要重写“可见性 api”的 getter,您可能必须重写滚动 api 方法和设置器(scrollTop 等)。对于可见性,仅检查if( document.hidden ) yourCallback();
以上是关于当 document.hidden 为 true 时,Chrome 中不会触发滚动事件。任何解决方法?的主要内容,如果未能解决你的问题,请参考以下文章