30-seconds-of-react项目:使用useBodyScrollLock钩子实现滚动锁定

30-seconds-of-react项目:使用useBodyScrollLock钩子实现滚动锁定

30-seconds-of-react Short React code snippets for all your development needs 30-seconds-of-react 项目地址: https://gitcode.com/gh_mirrors/30/30-seconds-of-react

什么是滚动锁定?

滚动锁定是一种常见的前端交互技术,主要用于模态框(Modal)、侧边栏菜单等场景。当这些组件出现时,我们通常希望禁止页面背景内容的滚动,以避免用户操作混乱,提升用户体验。

useBodyScrollLock钩子解析

这个自定义钩子通过修改body元素的overflow样式属性来实现滚动锁定:

const useBodyScrollLock = () => {
  React.useLayoutEffect(() => {
    // 获取body元素原始的overflow值
    const originalStyle = window.getComputedStyle(document.body).overflow;
    // 设置body元素overflow为hidden,禁止滚动
    document.body.style.overflow = 'hidden';
    // 组件卸载时恢复原始样式
    return () => (document.body.style.overflow = originalStyle);
  }, []);
};

技术要点解析

  1. useLayoutEffect:与useEffect类似,但会在DOM变更后同步触发。这里使用它确保在渲染前就锁定滚动,避免闪烁。

  2. getComputedStyle:获取元素当前计算后的样式值,这里用于保存body元素的原始overflow值。

  3. 清理函数:返回的函数会在组件卸载时执行,恢复body元素的原始overflow值,确保不影响页面其他部分。

实际应用示例

下面是一个完整的模态框组件示例,展示了如何使用useBodyScrollLock:

const Modal = ({ onClose }) => {
  useBodyScrollLock(); // 调用钩子锁定滚动

  return (
    <div style={{
      zIndex: 100, 
      background: 'rgba(0,0,0,0.25)', 
      display: 'flex',
      justifyContent: 'center', 
      alignItems: 'center'
    }}>
      <p 
        style={{ padding: 8, borderRadius: 8, background: '#fff' }}
        onClick={onClose}
      >
        滚动已锁定! <br /> 点击我解锁
      </p>
    </div>
  );
};

const MyApp = () => {
  const [modalOpen, setModalOpen] = React.useState(false);

  return (
    <div style={{
      height: '400vh', 
      textAlign: 'center', 
      paddingTop: 100,
      background: 'linear-gradient(to bottom, #1fa2ff, #12d8fa, #a6ffcb)'
    }}>
      <button onClick={() => setModalOpen(true)}>打开模态框</button>
      {modalOpen && <Modal onClose={() => setModalOpen(false)} />}
    </div>
  );
};

使用场景与注意事项

适用场景

  • 模态对话框
  • 全屏菜单
  • 图片查看器
  • 任何需要阻止背景滚动的交互组件

注意事项

  1. 性能影响:频繁切换滚动锁定可能会影响页面性能
  2. 嵌套使用:多个组件同时调用时需要注意样式恢复的顺序
  3. 移动端适配:某些移动设备可能需要额外处理touch事件
  4. 可访问性:确保锁定滚动时焦点管理得当,不影响键盘导航

进阶思考

对于更复杂的场景,可以考虑以下扩展:

  1. 添加对移动端touch事件的阻止
  2. 实现嵌套滚动锁定的计数机制
  3. 结合React Portal使用,处理不同层级的滚动锁定

这个简洁而强大的钩子展示了React自定义钩子在解决常见UI问题上的优雅之处,通过封装副作用逻辑,使组件代码更加清晰可维护。

30-seconds-of-react Short React code snippets for all your development needs 30-seconds-of-react 项目地址: https://gitcode.com/gh_mirrors/30/30-seconds-of-react

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

戚游焰Mildred

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

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

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

打赏作者

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

抵扣说明:

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

余额充值