有没有办法只检测水平滚动而不触发浏览器回流

新手上路,请多包涵

您可以使用以下方法检测任意元素上的浏览器滚动事件:

 element.addEventListener('scroll', function (event) {
    // do something
});

我希望能够区分垂直滚动和水平滚动并独立执行它们的操作。

我目前通过存储 element.scrollTop 和 element.scrollLeft 的值,然后在事件侦听器中比较它们来执行此操作。例如

var scrollLeft, scrollTop;
element.addEventListener('scroll', function (event) {
    if (scrollLeft !== element.scrollLeft) {
        // horizontally scrolled

        scrollLeft = element.scrollLeft;
    }

    if (scrollTop !== element.scrollTop) {
        // vertically scrolled

        scrollTop = element.scrollTop;
    }
});

这工作正常,但是从 https://gist.github.com/paulirish/5d52fb081b3570c81e3a 我读到读取 scrollLeft 或 scrollTop 值会导致回流。

有没有更好的方法来做到这一点而不会导致浏览器在滚动时重排?

原文由 magritte 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 310
2 个回答

我认为你的代码是正确的,因为在一天结束时你需要阅读其中一个属性来找出滚动方向,但这里避免性能问题的 关键限制事件,否则 scroll 事件触发太频繁,这是性能问题的根本原因。

因此,您的示例代码适用于限制 scroll 事件,如下所示:

 var ticking = false;
var lastScrollLeft = 0;
$(window).scroll(function() {
    if (!ticking) {
        window.requestAnimationFrame(function() {

            var documentScrollLeft = $(document).scrollLeft();
            if (lastScrollLeft != documentScrollLeft) {
                console.log('scroll x');
                lastScrollLeft = documentScrollLeft;
            }

            ticking = false;
        });
        ticking = true;
    }
});

来源: https ://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example

原文由 Nelson 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 position: absolute; 的元素从文档流中取出 (参见源代码)

考虑到这一点,您可以使用 CSS 使您的 element 绝对定位在其父级中……

 #parent{
    width: 500px;
    height: 100px;
    // ...or whatever dimensions you need the scroll area to be
    position: relative;
}
#element{
    position: absolute;
    top: 0px;
    left: 0px;
    bottom: 0px;
    right: 0px;
}

… 然后您可以随意阅读 element.scrollLeftelement.scrollTop 属性,就像您在原始问题中所做的那样,而不用担心重排整个 DOM 造成的瓶颈。

Google 的开发者指南中也推荐 这种方法。

原文由 Marquizzo 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题