【JS篇】通过 useEventListener 实现监听滚动条的滚动结束事件

功能背景

项目中遇到需要监听当前用户操作的滚动容器的滚动位置,用以获得当前用户正在查看的内容模块,便于制作导航条展示用户当前所查看的模块(类似页内导航功能)。故想要通过实时监听滚动位置,根据判断滚动停止来执行相应事件,但js中并没有监听滚动停止事件,只能通过在滚动的监听事件中增加定时器来判断滚动是否停止。
在这里插入图片描述

功能实现方式分析

  1. 初始时,使用 ahooks 的 useScroll,实时获取滚动位置数据进行操作,实现功能,但使用过程中发现滚动条不断改变位置的同时,scroll的值也在不断更新,查看源码发现在监听滚动条滚动过程中,也在不断进行setState操作,当页面功能复杂,dom节点较多的情况下,可能严重影响性能和体验。
// ahooks 中 useScroll 的源码部分:setPosition 执行的是内部封装的 useRafState, 本质上也是进行了 setState 操作
if (shouldUpdateRef.current(newPosition)) {
	setPosition(newPosition);
}
  1. 后来考虑通过 ahooks 的 useEventListener 监听滚动条滚动事件实现。但考虑到性能问题,需要判断滚动结束后再去获得滚动位置数据,并进行数据的操作。
  2. 通过设置监听器,在不停地触发滚动时,不会执行定时器内的方法,当滚动停止时,定时器前后两次获取的 scrollTop 应该是相同的,可以此作为判断依据。
  const scrollRef = useRef(null);
  // 滚动结束位置信息
  const [scrollPosition, setScrollPosition] = useState({top: 0, left: 0});
  const timer = useRef(null);
  const topValue = useRef(0);
  
  // 滚动事件监听
  useEventListener(
    'scroll',
    () => {
      clearTimeout(timer.current)
      topValue.current = scrollRef.current.scrollTop;
	  timer.current = setTimeout(()=>{
        if(scrollRef.current.scrollTop === topValue.current) {
          const position = {
            top: scrollRef.current.scrollTop,
            left: scrollRef.current.scrollLeft
          };
          setScrollPosition(position)
		  // TODO 执行后续滚动结束的事件
          // ...
        }
      }, 300);
    },
    { target: scrollRef },
  );

页面布局部分:container 为滚动容器,div1、div2、div3为滚动内容,滚动停止时,将获取当前滚动条的scrollTop, 并以此判断当前停留在哪个div上,从而进行标记,以此实现页面导航功能。

	<div className='container' style={{position: 'relative'}} ref={scrollRef}>
        <div data-anchorpointid='div1'>div1</div>
        <div data-anchorpointid='div2'>div2</div>
        <div data-anchorpointid='div3'>div3</div>
	</div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章魚尐芄子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值