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

mag*_*tte 17 javascript html5 reflow

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

element.addEventListener('scroll', function (event) {
    // do something
});
Run Code Online (Sandbox Code Playgroud)

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

我目前正在通过存储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;
    }
});
Run Code Online (Sandbox Code Playgroud)

这很好,但是从https://gist.github.com/paulirish/5d52fb081b3570c81e3a我读到读取scrollLeft或scrollTop值会导致重排.

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

Nel*_*son 9

我认为你的代码是正确的,因为在一天结束时你需要阅读其中一个属性来找出滚动方向,但这里避免性能问题的关键限制事件,因为否则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;
    }
});
Run Code Online (Sandbox Code Playgroud)

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


Mar*_*zzo 6

使用的元素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;
}
Run Code Online (Sandbox Code Playgroud)

...然后您可以随意阅读element.scrollLeftelement.scrollTop属性,就像您在原始问题中所做的那样,而不必担心回流整个 DOM 会遇到瓶颈。

Google 的开发人员指南 中推荐了这种方法。


Ben*_*est 6

直接听输入怎么样?

element.addEventListener('wheel', e => {
    if ( e.deltaX !== 0 ) {
        horizontal();
    }
    if ( e.deltaY !== 0 ) {
        vertical();
    }
})
Run Code Online (Sandbox Code Playgroud)

您可能还需要创建自己的滚动条并监听滚动条的拖动。这是在重新发明轮子(笑),但是嘿,没有scrollTopscrollLeft在眼前。