前言
如果你的项目没有引入 jquery,但是又想方便地控制滚动条,这时候,react-smooth-scroll-hoook可能会帮上忙。
useSmoothScroll
用法
useSmoothScroll 核心在于 scrollTo 方法,可传入目标节点或者滚动距离,以自定义的速度滚动到该节点。
1 | export const Demo = () => { |
Demo
原理
- 初始化容器 dom 节点
- 监听滚动条的状态,如滚动条是否触达容器的两端。
- scrollTo 方法:通过 requestAnimationFrame 去设置容器的 scrollLeft/scrollTop,直到滚动到目标位置。
细节
传入目标节点,计算滚动距离
- 如果滚动容器是根元素 html 或者 body,那么直接取当前目标节点的上边距(getBoundingClientRect().top/left),否则,还要减去父容器的上边距。
事件监听
- 监听滚动条的属性变化,更新滚动容器的大小。
- 监听窗口的 resize 事件,更新滚动容器的大小。
- 监听滚动容器内子元素的 dom 变化,更新滚动条位置状态。
- 监听容器的 scroll 事件,更新滚动条位置状态。
useScrollWatch
用法
useScrollWatch 用于解决类似导航栏定位的问题,可以获取当前滚动条位于传入 list 节点数组中的哪个节点。
1 | export const ScrollConatainerMode = () => { |
Demo
原理
- 初始化节点 list
- 监听 scroll 事件和子元素的变化,根据滚动条当前的位置,计算出当前滚动条位于 list 中的哪个节点。
细节
- 需要注意,滚动条的初始点不是父容器的顶部,而是父容器下第一个子元素的顶部(即需要考虑内边距对滚动容器起点的影响)
搭建文档
生成参数表格
使用 storybook,集成 react-docgen-typescript-loader
,轻松通过 TS 类型自动生成文档。具体配置如下见*.storybook/main.js
*
**
将 stories 文件用于 CodeSandbox
我们可以将文档展示的 demo 一起用于 codesandbox 展示,具体见 ./example
编写测试
单元测试
为工具方法编写单元测试,具体见 ./test/specs
,执行 test 命令
1 | tsdx test --passWithNoTests --config jest.unit.config.js |
e2e 测试
对于组件和强依赖 dom 的一些插件或者 hook,我们通过端到端测试模拟,摆脱人工测试,实现自动化。
测试滚动的有效性
我们通过到列表中的某个元素后,如果该元素的上一个元素在视口中不可见,确定滚动的有效性。
经过文档的反差,我使用了 isIntersectingViewport
这个方法,通过该方法,可以判断某个元素是否真正离开屏幕或者在视口中不可见。
isIntersectingViewport 的缺陷
在这个过程中,我重写了官方的 isIntersectingViewport
方法,让其支持传入一个误差值。
为什么呢?由于滑动的距离是通过运算得出的,无可避免地产生了精度问题,导致某元素即使表面上完全不可见了,却由于精度问题, isIntersectingViewport
返回了错误的判断(例如期望值是 0,可能返回 0.000000001)。
以下为重写代码,可以重点关注增加的 threshold
,传入后 最终的显示比例会加上这个值进行精度修正。
该问题已经向 puppetter 提交了 pr,但尚未处理。https://github.com/puppeteer/puppeteer/pull/6497
1 | async function isIntersectingViewport( |
在这里,我们在使用 puppeteer 提供的 api 的时候,需要注意,回调函数在浏览器环境下执行,而不是在 node 环境下,所以两边的环境变量不一样,是不能相互读取的。
发布
使用 github-action 完成发布,具体脚本,流程如下:
- 在
stories/**
和example.**
或者Reame.md
发生变更的时候,我们执行文档发布作业。 - 在
src/**
源码发生变更的时候,我们执行 npm 发布和文档发布作业。