网易首页 > 网易号 > 正文 申请入驻

React团队藏了3年的钩子库,47行代码干翻5个动画库

0
分享至


去年有个数据挺有意思:npm上带"scroll"关键词的动画库,周下载量加起来超过1.5亿次。但你去问前端工程师,十个里有八个会吐槽——"我就想要个进度条,它给我塞了200KB的贝塞尔曲线"。

这事怪不了开发者。滚动监听在React里是个典型的"看起来简单,做起来漏"的活儿。节流、方向判断、边界检测、被动事件监听,随便一个需求都能让你写出一堆 imperative 代码(命令式代码)。然后你发现问题还没完:服务端渲染时 `window` 不存在,iOS 的橡皮筋回弹会误判方向,容器的 `overflow` 层级搞不清该监听谁。

ReactUse 这个库的存在感一直很奇怪。GitHub 标星不多,但你去翻 Ant Design、Arco Design 的源码,会发现它们内部都在用。它不做动画,只做一件事:把浏览器原生能力包装成可组合的 Hooks。100 多个钩子,平均每个不到 50 行代码。

这篇我们拿 6 个最常见的滚动场景开刀。每个场景先给你看手写实现的问题,再换 ReactUse 的解法。看完你会明白为什么有些团队宁愿自己造轮子,也不碰那些"全能"动画库。

场景一:滚动进度条,但用户到底看完没有

最简单的进度条实现,上面代码已经给了。`scrollTop` 除以可滚动高度,绑个 `fixed` 定位的 div,完事。但产品经理第二天就会来找你:"能不能加个'已读完'的标记?"

这意味着你要检测用户是否到达底部。 naive 的做法是判断 `scrollTop + clientHeight === scrollHeight`,但不同浏览器的取整策略不一样,Chrome 可能差 1px,Safari 可能差 3px。于是你加个阈值,比如距离底部 50px 算到达。然后发现阈值在移动端和桌面端表现不一致,再改成动态计算。

ReactUse 的 `useScroll` 把这些都包了。它返回的 `arrivedState` 用 IntersectionObserver 检测边界,比数学计算更可靠。代码变成这样:

const { y, arrivedState } = useScroll(elRef); // arrivedState.bottom 直接告诉你是否触底

方向检测也换了实现。不是比较前后两次 `scrollTop`,而是维护一个滑动窗口,过滤掉橡皮筋回弹导致的微小抖动。你在 iPhone 上快速滑动后松手,进度条不会抽风。

场景二:吸顶导航,但高度会变的场景

吸顶效果(sticky header)的坑在于:你的导航栏高度可能变化。用户往下滚,导航栏缩小并固定;往上滚,又展开恢复原状。这个"缩小"的动画如果直接用 CSS `transform: scale`,会导致内部文字模糊,因为 GPU 渲染的纹理被压缩了。


正确的做法是用 `height` 动画,但这就涉及动态计算占位高度。导航栏从 80px 缩到 48px,下面的内容要同步 `paddingTop` 变化,否则会出现跳跃。手写代码里,你需要用 `ResizeObserver` 监听导航栏高度,再用 `useScroll` 监听位置,两个 effect 之间还要同步状态。

ReactUse 的 `useElementBounding` 把尺寸和位置监听合成一个钩子。它内部用 `ResizeObserver` + `IntersectionObserver` 双保险,返回的 `height` 是响应式的,直接拿来算 `paddingTop` 就行。SSR 场景下它返回 `{ width: 0, height: 0 }`,不会报错。

有个细节:很多团队吸顶时会加个阴影或背景色变化。`useElementBounding` 返回的 `top` 值在吸顶瞬间会突变,直接拿来做渐变动画会闪。ReactUse 的做法是内部维护一个 `isStuck` 状态,用阈值滞后避免抖动。

场景三:模态框锁屏,但滚动条宽度要处理

打开模态框时锁定背景滚动,这个需求看起来就是 `overflow: hidden`。但 Windows 上滚动条占据 17px 宽度,隐藏后页面会右移,内容产生"抖动"。macOS 的滚动条是覆盖式的,没有这个问题。

标准的修复方案是计算滚动条宽度,给 `body` 加等宽的 `paddingRight`。但计算宽度需要创建一个不可见的滚动容器,测量后销毁,这段代码没人想写第二遍。更麻烦的是:如果页面本来就没有滚动条(内容没撑满),你加了 `paddingRight` 反而会出现白边。

ReactUse 的 `useScrollLock` 处理了所有这些边缘情况。它内部用 `window.innerWidth - document.documentElement.clientWidth` 算宽度,比创建临时 DOM 更快。还会检查 `getComputedStyle` 确认当前是否有滚动条,避免误伤。

一个容易忽略的点:锁屏时要记住之前的 `overflow` 值,关闭时恢复。如果用户打开模态框前,页面已经是 `overflow: hidden`(比如另一个模态框),你不能粗暴地改成 `auto`。`useScrollLock` 用栈结构管理多个锁屏请求,后开的先关,不会互相覆盖。

场景四:锚点滚动,但要考虑用户偏好

"点击按钮平滑滚动到对应章节"这个功能,`scrollIntoView({ behavior: 'smooth' })` 就能做。但 `prefers-reduced-motion` 媒体查询你要不要支持?有些用户因为前庭功能障碍,看到平滑滚动会头晕。

ReactUse 的 `useSmoothScroll` 内部检测了这个媒体查询,如果用户设置了减少动画,自动降级为即时跳转。它还封装了 `scrollTo` 和 `scrollBy` 两种模式,支持相对偏移(比如"往上滚 200px")。

另一个细节:如果目标元素在可滚动容器内部,而不是 `document`,`scrollIntoView` 会同时滚动容器和页面,产生双重动画。`useSmoothScroll` 允许你指定滚动容器,只操作那一层。


性能方面,它用 `requestAnimationFrame` 做缓动计算,而不是 CSS 的 `scroll-behavior`。原因是后者无法中断,用户中途点击其他锚点,动画会排队执行,感觉很卡。`requestAnimationFrame` 可以随时取消,响应更快。

场景五:元素可见性检测,但阈值要动态

IntersectionObserver 是检测元素是否进入视口的原生 API,但直接用起来很啰嗦。你要创建 observer 实例,管理回调引用,还要记得在元素卸载时 `unobserve`。如果多个组件都需要监听,代码重复得一塌糊涂。

ReactUse 的 `useIntersectionObserver` 把它压缩成一行。默认配置是元素出现 10% 就触发,你可以改成"完全可见"或自定义阈值数组。一个常见的需求是:图片懒加载时,希望在距离视口 200px 时就开始加载,`rootMargin` 参数直接支持。

动态阈值是个高级用法。比如你做无限滚动列表,希望用户快滑到底部时加载更多,但"快滑到"的定义随列表长度变化。短列表剩 3 个元素就加载,长列表剩 10 个。`useIntersectionObserver` 的 `threshold` 可以是响应式的,配合 `useMemo` 动态计算。

SSR 兼容性处理得也干净。服务端没有 `IntersectionObserver`,钩子直接返回 `false`,不会尝试访问 `window`。

场景六:滚动联动动画,但不用动画库

最复杂的场景:滚动位置驱动动画,比如视差滚动、文字颜色渐变、图片缩放。传统做法是用 GSAP ScrollTrigger 或 Framer Motion,但它们都带了完整的动画引擎,体积不小。

ReactUse 提供了 `useScrollProgress`,把滚动位置映射到 0-1 的进度值。你可以拿这个值直接驱动 CSS 变量,或者配合 `useRafFn` 做逐帧更新。没有缓动函数库,没有关键帧系统,就是纯粹的数据流。

一个实战技巧:配合 `useSpring`(另一个 ReactUse 钩子)可以给进度值加物理效果。用户停止滚动后,动画不会戛然而止,而是带一点惯性衰减。这个"弹簧"效果完全基于 `requestAnimationFrame`,没有依赖任何动画库。

性能上,`useScrollProgress` 内部做了节流,默认 16ms(约 60fps)触发一次。你可以调得更粗,比如 100ms,用于不那么敏感的联动效果。

ReactUse 的作者 Anthony Fu 在文档里写过一句话:「这些钩子不是让你少写代码,是让你写对代码。」看完这六个场景的对比,你可能会重新评估自己的技术选型——那些下载量过亿的动画库,你真的需要吗?

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
52:141,匈牙利民调出炉后,马克龙率先发难,又有两国曝私下交易

52:141,匈牙利民调出炉后,马克龙率先发难,又有两国曝私下交易

策略述
2026-04-10 16:22:09
一觉醒来,斯诺克3冠军翻车!丁俊晖克星3-1被逆转,70后名将降级

一觉醒来,斯诺克3冠军翻车!丁俊晖克星3-1被逆转,70后名将降级

刘姚尧的文字城堡
2026-04-10 07:47:34
利物浦官宣32岁传奇自由身离队!效力9年夺9冠,3大豪门或成下家

利物浦官宣32岁传奇自由身离队!效力9年夺9冠,3大豪门或成下家

我爱英超
2026-04-10 06:35:51
证监会,重磅发布!

证监会,重磅发布!

中国基金报
2026-04-10 18:23:43
对华签证再放宽,14城居民手握10年签,日本旅游业坐不住了吗?

对华签证再放宽,14城居民手握10年签,日本旅游业坐不住了吗?

东京在线
2026-04-10 16:23:40
中央一锤定音!6月1日起全国统一执行,家家户户用水将迎7大变化

中央一锤定音!6月1日起全国统一执行,家家户户用水将迎7大变化

三农雷哥
2026-04-10 17:43:46
成龙没想到,自己那不成器的儿子房祖名,竟成他患病后的“救赎”

成龙没想到,自己那不成器的儿子房祖名,竟成他患病后的“救赎”

阿纂看事
2026-04-10 11:45:27
全红婵群内被骂果断报警!周继红霸气护犊:管你是谁依法办!

全红婵群内被骂果断报警!周继红霸气护犊:管你是谁依法办!

不似少年游
2026-04-09 17:13:43
汽柴油“由涨变跌”,大降超0.63元/升,4月21日油价调整,大降中

汽柴油“由涨变跌”,大降超0.63元/升,4月21日油价调整,大降中

油价早知道
2026-04-11 01:24:26
拒挂国旗、订单全给日韩,被停止合作封锁航线的长荣,今咎由自取

拒挂国旗、订单全给日韩,被停止合作封锁航线的长荣,今咎由自取

混沌录
2026-04-10 22:53:08
别只当他是射手!湖人捡到全能宝藏,雷迪克都为他鸣不平

别只当他是射手!湖人捡到全能宝藏,雷迪克都为他鸣不平

钱说体育
2026-04-11 01:02:26
WTT太原赛一夜八强落定:国乒男单仅剩两将,中日女单包揽

WTT太原赛一夜八强落定:国乒男单仅剩两将,中日女单包揽

陈锌特色美食
2026-04-11 02:36:08
难以置信啊!一餐吃掉562339.80元,上海一张消费清单刷爆网络

难以置信啊!一餐吃掉562339.80元,上海一张消费清单刷爆网络

火山詩话
2026-04-10 06:49:46
中国实验室不能做检测了,美国掐断认证环节,电子制造可能得洗牌

中国实验室不能做检测了,美国掐断认证环节,电子制造可能得洗牌

林子说事
2026-04-10 12:21:47
6个进球全是乌龙!10岁孩子为何踢假球?赛制安排不合理引发乱象

6个进球全是乌龙!10岁孩子为何踢假球?赛制安排不合理引发乱象

中国足球的那些事儿
2026-04-10 13:16:45
开路虎加油逃单后续:正脸曝光已死,身份被扒还是惯犯,警方介入

开路虎加油逃单后续:正脸曝光已死,身份被扒还是惯犯,警方介入

潮鹿逐梦
2026-04-10 12:03:49
iPhone Ultra 售价曝光,国行起售价 17,999 !

iPhone Ultra 售价曝光,国行起售价 17,999 !

XCiOS俱乐部
2026-04-09 13:52:43
有没有人敢爆自己的瓜?网友:确定玩这么大吗?

有没有人敢爆自己的瓜?网友:确定玩这么大吗?

夜深爱杂谈
2026-02-18 20:55:58
广东一家制衣厂仅有一位男员工,百余名女同事围着轮流投喂呵护

广东一家制衣厂仅有一位男员工,百余名女同事围着轮流投喂呵护

捣蛋窝
2026-04-07 13:22:20
真相来了!浓眉亲承:因为锡安我才去了湖人,如果选莫兰特绝不走

真相来了!浓眉亲承:因为锡安我才去了湖人,如果选莫兰特绝不走

夜白侃球
2026-04-10 14:41:02
2026-04-11 03:47:00
码上闲叙
码上闲叙
有态度网友ytd
1527文章数 10关注度
往期回顾 全部

科技要闻

马斯克狂发大火箭也养不起AI 年亏50亿美元

头条要闻

特朗普:美军舰已装最先进武器 未来24小时成关键窗口

头条要闻

特朗普:美军舰已装最先进武器 未来24小时成关键窗口

体育要闻

17岁赚了一百万美元,25岁被CBA裁员

娱乐要闻

黄景瑜王玉雯否认恋情!聚会细节被扒

财经要闻

李强主持召开经济形势专家和企业家座谈会

汽车要闻

搭载第二代刀片电池及闪充技术 腾势N8L闪充版预售35万起

态度原创

游戏
本地
教育
亲子
公开课

《霍格沃茨之遗2》传闻2027年发售!今年有望首曝

本地新闻

12吨巧克力有难,全网化身超级侦探添乱

教育要闻

2026年最具“性价比”的4个专业,本科就业率高,考研容易上岸!

亲子要闻

孩子近视怎么防、不爱刷牙怎么办?专家现场拆解4大防护举措

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版