useHashAnchor
页内锚点的两件事。原生 hash 跳转只算一次落点,跳完上面的内容再长高(异步列表落地、图片撑开、 手动展开)目标就被推走了;hash 留在地址栏上,刷新又跳回一个早已离开的位置。
XScrollRail 内部就是它,页面用了 XScrollRail 就不必再调;一页只挂一处。
基础
跳转后内容长高
选项
| 选项 | 类型 | 说明 |
|---|---|---|
align | MaybeRefOrGetter<boolean> | 跳完纠偏,缺省开启 |
clearHash | MaybeRefOrGetter<boolean> | 用户滚走后清掉过期 hash,缺省开启 |
settleMs | number | 跳转后还认多久的高度变化,缺省 4000 毫秒 |
返回值
| 名称 | 类型 | 说明 |
|---|---|---|
follow() | () => void | 按当前地址的 hash 开始纠偏与过期判断;路由改 hash 后调 |
判据
- 纠偏:跳完逐帧比目标在文档里的位置,变了就瞬间贴齐(纠偏不是导航,平滑滚会跟正在进行的跳转
打架),超时或用户一动手(滚轮、触摸、指针按下、按键)就撒手。比位置而不是观察某个盒子的尺寸:
撑开它的可能是任意一层祖先。贴齐用
scrollIntoView,吸顶栏的让位交给目标的scroll-margin-top。 - 清 hash:目标先被看见、再整块滚出视口,才算用户离开了它。不按「当前章节不再是它」判——
比视口矮的节永远占不到视口中部,那样会在刚跳到时就把 hash 抹掉,而 hash 指向的也未必是章节。
清理用
replaceState并保留history.state(路由的前进后退记录在里面),位置恢复交给浏览器 原生的 scrollRestoration。 - 只认原生
hashchange(<a href="#x">)。经路由pushState改的 hash 不触发它,那种跳转 之后调一次follow()。
判据里的纯逻辑单独导出:hashTargetId(hash)(解码、不经选择器,#1-intro 这类 id 也取得到)、
followDrift(options)、createStaleTracker()。