简体   繁体   English

如何删除滚动事件监听器?

[英]How to remove scroll event listener?

I am trying to remove scroll event listener when I scroll to some element.当我滚动到某个元素时,我试图删除滚动事件监听器。 What I am trying to do is call a click event when some elements are in a viewport.我想做的是当某些元素在视口中时调用点击事件。 The problem is that the click event keeps calling all the time or after first call not at all.问题是点击事件一直在调用,或者在第一次调用之后根本不调用。 (Sorry - difficult to explain) and I would like to remove the scroll event to stop calling the click function. (抱歉 - 难以解释)我想删除滚动事件以停止调用点击 function。

My code:我的代码:

   window.addEventListener('scroll', () => {
   window.onscroll = slideMenu;

        // offsetTop - the distance of the current element relative to the top;
        if (window.scrollY > elementTarget.offsetTop) {
            const scrolledPx = (window.scrollY - elementTarget.offsetTop);

            // going forward one step
            if (scrolledPx < viewportHeight) {
                // console.log('section one');
                const link = document.getElementById('2');
                if (link.stopclik === undefined) {
                    link.click();
                    link.stopclik = true;
                }
            }

            // SECOND STEP
            if (viewportHeight < scrolledPx && (viewportHeight * 2) > scrolledPx) {
                console.log('section two');

                // Initial state
                let scrollPos = 0;
                window.addEventListener('scroll', () => {
                    if ((document.body.getBoundingClientRect()).top > scrollPos) { // UP
                        const link1 = document.getElementById('1');
                        link1.stopclik = undefined;
                        if (link1.stopclik === undefined) {
                            link1.click();
                            link1.stopclik = true;
                        }
                    } else {
                        console.log('down');
                    }
                    // saves the new position for iteration.
                    scrollPos = (document.body.getBoundingClientRect()).top;
                });
            }

            if ((viewportHeight * 2) < scrolledPx && (viewportHeight * 3) > scrolledPx) {
                console.log('section three');
            }

            const moveInPercent = scrolledPx / base;
            const move = -1 * (moveInPercent);

            innerWrapper.style.transform = `translate(${move}%)`;
        }
    });

You can only remove event listeners on external functions. 您只能删除外部函数上的事件侦听器。 You cannot remove event listeners on anonymous functions, like you have used. 您不能像以前那样删除匿名函数上的事件侦听器。

Replace this code 替换此代码

window.addEventListener('scroll', () => { ... };

and do this instead 并改为这样做

window.addEventListener('scroll', someFunction);

Then move your function logic into the function 然后将函数逻辑移到函数中

function someFunction() {
  // add logic here
}

You can then remove the click listener when some condition is met ie when the element is in the viewport 然后,当满足某些条件时(即,元素在视口中时),可以删除单击侦听器

window.removeEventListener('scroll', someFunction);

Instead of listening to scroll event you should try using Intersection Observer (IO) Listening to scroll event and calculating the position of elements on each scroll can be bad for performance. 与其侦听滚动事件,不如尝试使用Intersection Observer(IO)侦听滚动事件并计算每个滚动上元素的位置可能会降低性能。 With IO you can use a callback function whenever two elements on the page are intersecting with each other or intersecting with the viewport. 使用IO时,只要页面上的两个元素相交或与视口相交,就可以使用回调函数。

To use IO you first have to specify the options for IO. 要使用IO,首先必须指定IO选项。 Since you want to check if your element is in view, leave the root element out. 由于您要检查元素是否在视图中,因此请忽略root元素。

let options = {
  rootMargin: '0px',
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);

Then you specify which elements you want to watch: 然后,指定要观看的元素:

let target = slideMenu; //document.querySelector('#oneElement') or document.querySelectorAll('.multiple-elements')
observer.observe(target); // if you have multiple elements, loop through them to add observer

Lastly you have to define what should happen once the element is in the viewport: 最后,您必须定义一旦元素进入视口后应该发生的情况:

let callback = (entries, observer) => { 
  entries.forEach(entry => {
    // Each entry describes an intersection change for one observed
    // target element:
  });
};

You can also unobserve an element if you don't need the observer anymore. 如果您不再需要观察者,也可以取消观察元素

Check this polyfill from w3c to support older browsers. 从w3c选中此polyfill以支持较旧的浏览器。

Here is my scenario/code, call removeEventListener as return() in the useEffect hook.这是我的场景/代码,在useEffect挂钩中将removeEventListener调用为return()

  const detectPageScroll = () => {
    if (window.pageYOffset > YOFFSET && showDrawer) {
      // do something
    }
  };

  React.useEffect(() => {
    if (showDrawer) {
      window.addEventListener("scroll", detectPageScroll);
    }
    return () => {
      window.removeEventListener("scroll", detectPageScroll);
    };
  }, [showDrawer]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM