news 2026/10/6 2:03:47

vue-devui Anchor 锚点组件实战指南:指令式页面内跳转与滚动激活

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
vue-devui Anchor 锚点组件实战指南:指令式页面内跳转与滚动激活
  • 前端
  • UI组件
  • 设计系统

【免费下载链接】vue-devui

基于全新 DevUI Design 设计体系的 Vue3 组件库,面向研发工具的开源前端解决方案。

项目地址:https://gitcode.com/DevCloudFE/vue-devui
点击查看免费下载

在长文档、帮助中心或研发工具等需要「页内快速导航」的场景中,Anchor 锚点组件通过在页面上建立链接与目标区块的映射关系,实现点击链接平滑滚动到指定位置,并在滚动过程中自动高亮当前所在章节。本文基于 vue-devui 组件库的 Anchor 组件(文档见 packages/devui-vue/docs/components/anchor/index.md),完整讲解其三条指令v-d-anchor-box、v-d-anchor-link、v-d-anchor的用法、参数与激活事件,并结合仓库源码剖析其滚动、高亮与 URL Hash 同步的实现原理,帮助读者在项目里快速落地「目录导航 + 章节定位」功能。

组件概览与何时使用

Anchor 是「跳转到页面指定位置的组件」,属于 vue-devui 导航类(category: '导航')组件。当页面内容较长、需要在各个部分之间实现快速跳转时即可使用,典型场景包括:

  • 文档页 / 帮助中心左侧的章节目录
  • 长表单分块填写时的步骤导航
  • 研发工具中的配置项快速定位

与常规「一个组件 + 一个配置对象」的封装方式不同,vue-devui 的 Anchor 以**指令(directive)**为主要交互载体,由三个指令协作完成全部能力,由 packages/devui-vue/devui/anchor/index.ts 统一注册:

install(app: App): void { app.directive(dAnchor.name, dAnchor); app.directive(dAnchorLink.name, dAnchorLink); app.directive(dAnchorBox.name, dAnchorBox); app.component(Anchor.name, Anchor); }

即:全局注册DAnchorBox、DAnchorLink、DAnchor三条指令,同时导出同名Anchor组件(当前Anchor组件本体为占位容器,功能主要由指令承担,组件实现见 anchor.tsx)。

三个指令各司其职:

指令职责
v-d-anchor-box定义扫描锚点的滚动容器,放在dAnchor与dAnchorLink的公共父节点上,负责锚点和链接之间的通信
v-d-anchor-link定义一个锚点链接,点击后平滑滑动到对应锚点
v-d-anchor定义一个锚点(章节区块),并参与滚动激活状态的判定

基本用法

在页面中使用时,只需要一个容器节点,内部用无序列表承载链接、用普通块级元素承载锚点区块。参考文档示例与 demo.tsx:

<!-- class="scrollTarget" 加上这个类名是局部滚动,不加是全局滚动 --> <div v-d-anchor-box className="scrollTarget"> <ul> <li v-d-anchor-link="anchorlink-one">anchorlink-one</li> <li v-d-anchor-link="anchorlink-two">anchorlink-two</li> <li v-d-anchor-link="anchorlink-three">anchorlink-three</li> <li v-d-anchor-link="anchorlink-four">anchorlink-four</li> </ul> <div> <div v-d-anchor="anchorlink-one"> anchorlink-one1 </div> <div v-d-anchor="anchorlink-two"> anchorlink-two </div> <div v-d-anchor="anchorlink-three"> anchorlink-three </div> <div v-d-anchor="anchorlink-four"> anchorlink-four </div> </div> </div>

全局滚动与局部滚动

示例代码中有一处关键注释:容器上添加scrollTarget类名即为局部滚动,不加则为全局滚动。

  • 全局滚动:滚动事件绑定在window上,锚点位置按document.documentElement.scrollTop || document.body.scrollTop计算,适用于整页内容较长、目录固定于一侧的场景;
  • 局部滚动:滚动事件绑定在容器元素上,按scrollTarget容器的scrollTop计算,适用于页面内嵌一个独立滚动区域(如面板内长列表)的场景。

从 d-anchor-box.ts 的源码可以看到容器对这两种模式的判定逻辑:

window.onscroll = function () { windoScrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (!document.getElementsByClassName('scrollTarget').length) { // 全局滚动:根据滚动位置切换 sidebar 的定位(absolute/fixed) } else { cssChange(mysidebar, 'absolute', div.scrollTop, 0); } }; // 容器自身的滚动事件 addEvent?.(div, 'scroll', function () { if (document.getElementsByClassName('scrollTarget').length) { cssChange(mysidebar, 'fixed', div.getBoundingClientRect().top, div.getBoundingClientRect().left); } });

此外,d-anchor-box挂载时会给容器生成一个随机 id(复用shared/utils中的randomId工具,见 random-id.ts),并追加mycontainer、mymain类名,作为后续侧边导航定位、滚动监听的作用域标识。

Anchor:定义一个锚点

v-d-anchor用于在页面中定义一个锚点(章节区块),是滚动激活判定的目标单元。

Anchor 参数

参数类型默认说明
dAnchorstring--必选,设置一个锚点的名字
anchorActivestring--可选,锚点处于激活状态时,模块生效对应的 CSS 类名

源码中的挂载行为

在 d-anchor.ts 中,指令挂载(mounted)时会完成以下动作:

  1. 若父节点没有类名,则补上mycontent(右侧内容区样式);
  2. 在元素内部插入一个隐藏的<a class="box-anchor" href="#锚点名">,作为锚点映射关系中的 Hash 载体,供链接查询与匹配;
  3. 给元素设置section-block类名,并写入name="锚点名"属性——点击链接时正是通过document.getElementsByName(binding.value)找到目标区块的;
  4. 绑定onclick,点击锚点区块时通过hightLightFn高亮对应的链接。
mounted(el: HTMLElement, binding: Bind): void { const parent: Element = el.parentNode as Element; if (!parent.className) { parent.className = 'mycontent'; } el.innerHTML = '<a class="box-anchor" style="display:none" href="#' + binding.value + '">?</a>' + el.innerHTML; el.className = 'section-block'; el.setAttribute('name', binding.value); el.onclick = () => { hightLightFn(binding.value); }; }

对应的默认样式在 anchor.scss 中定义:.section-block有min-height: 200px与底部虚线分隔,保证每个章节区块有足够的可点击/可判定区域。

Anchor 锚点激活事件

锚点被激活时,组件会自动在锚点元素上添加对应的 CSS 类,用来区分「激活是由什么动作触发的」,便于开发者针对不同触发来源定制样式:

CSS 类名代表意义
anchor-active-by-anchor-link点击锚点链接激活
anchor-active-by-scroll容器滚动到锚点位置激活
anchor-active-by-click-inside点击锚点内部内容激活
anchor-active-by-initial初始化滚动条位置激活

这些类名配合section-block.active前缀使用。例如 anchor.scss 中内置的「点击链接后区块闪烁高亮」动画即利用了第一类激活:

.section-block.active.anchor-active-by-anchor-link { -webkit-animation: hightlight-and-disapear 3s linear 1; animation: hightlight-and-disapear 3s linear 1; }

动画hightlight-and-disapear在 10%~50% 时间点给区块绘制var(--devui-brand, #5e7ce0)的描边并逐渐淡出,实现「定位到目标后短暂高亮提醒」的视觉反馈,主题色通过 DevUI Design 变量接入主题系统。

AnchorLink:定义一个锚点链接

v-d-anchor-link用于定义目录中的链接项,点击后会平滑滑动到对应的锚点区块;当滚动使锚点位于页面顶部附近时,对应链接也会被激活并高亮。

AnchorLink 参数

参数类型默认说明
dAnchorLinkstring--必选,点击滑动的目标锚点的名字
anchorActivestring--可选,锚点处于激活状态时,链接生效对应的 CSS 类名

源码中的挂载与点击行为

在 d-anchor-link.ts 中,链接项挂载时会:

  1. 若父节点(通常是<ul>)没有类名,则补上mysidebar step-nav,使其具备侧边导航的样式与结构约定;
  2. 为链接项设置bar-link-item类名,并追加隐藏的<a class="d-d-anchor" href="#锚点名">;
  3. 用锚点名作为元素id,便于滚动激活时通过document.getElementById定位高亮;
  4. 绑定onclick:先根据页面是否存在scrollTarget决定滚动容器(局部滚动取容器元素、全局滚动取window),再调用scrollToControl执行平滑滚动。
el.onclick = () => { let scrollContainer: IScrollContainer; const scollToDomY = document.getElementsByName(binding.value)[0]; document.getElementsByClassName('scrollTarget').length ? scrollContainer = (document.getElementsByClassName('scrollTarget')[0] as IScrollContainer) : scrollContainer = window as IScrollContainer; scrollToControl(scollToDomY, scrollContainer); };

scrollToControl与平滑滚动实现位于 utils.ts:它计算目标区块相对容器的距离,按固定步长(timeoutIntervalSpeed = 10)通过多次setTimeout逐帧scrollBy,形成平滑滚动效果;滚动结束后再通过history.replaceState将当前锚点 Hash 同步到地址栏,并触发对应链接高亮:

function scrollSmoothly(scrollPos: number, repeatTimes: number, container: HTMLElement): void { if (repeatCount <= repeatTimes) { scrollPos > 0 ? container.scrollBy(0, timeoutIntervalSpeed) : container.scrollBy(0, -timeoutIntervalSpeed); } else { repeatCount = 0; clearTimeout(cTimeout); history.replaceState(null, '', document.location.pathname + '#' + hashName); hightLightFn(hashName); ... } repeatCount++; cTimeout = setTimeout(() => { scrollSmoothly(scrollPos, repeatTimes, container); }, 10); }

滚动过程中的链接自动高亮

d-anchor-box挂载时会调用setActiveLink(timeId)建立「链接 ↔ 锚点」的映射关系(见 d-anchor-box.ts):

  • 通过.step-nav > li.bar-link-item > a收集当前容器作用域内的全部链接;
  • 通过.box-anchor收集页面内全部锚点,并按hash值把链接与锚点一一配对;
  • 在滚动事件(onScroll,300ms 节流防抖)触发时,依据当前scrollTop与各锚点位置判断当前应处于哪个章节,命中后history.replaceState更新地址栏 Hash、activateLink高亮对应链接,并向上为父级目录项同步active类。
const onScroll = throttleAndDebounce(setActiveLink, 300);

高亮切换统一由hightLightFn完成:先清空侧边栏中所有带active的项,再为当前命中的链接 id 添加active类(见 utils.ts)。默认激活态样式同样定义在 anchor.scss 中——li.active/li:hover时文字变为品牌色var(--devui-brand-active, #526ecc),并通过::before圆形节点和竖线连接线构建出「步骤式」目录的视觉层级。

AnchorBox:锚点通信容器

v-d-anchor-box是锚点功能的前提——必须有一个容器,否则功能无法使用。它必须放置在dAnchor与dAnchorLink的公共父节点上,负责:

  1. 生成容器唯一 id,并追加mycontainer/mymain类名作为内部作用域标识;
  2. 监听window滚动(全局滚动)或容器自身滚动(局部滚动),驱动链接高亮与 Hash 更新;
  3. 根据滚动位置切换侧边导航(.mysidebar)的定位方式:页面滚动至容器范围内时使用fixed跟随,超出范围后回退为absolute,实现「目录吸顶/随动」效果(对应源码 d-anchor-box.ts 中的cssChange与window.onscroll逻辑);
  4. 监听window.resize,在窗口尺寸变化时重置侧边导航为absolute定位。

同时,侧边导航的默认宽度为240px(见 anchor.scss 中.mysidebar与.step-nav的定义),内容区.mycontent通过margin-left: 240px与目录形成左右分栏布局。

实践要点与注意事项

  • 三个指令必须配套使用:v-d-anchor-box是链路入口(缺少它则滚动监听与链接匹配无法工作),v-d-anchor-link负责触发,v-d-anchor负责承载与命中判定;
  • 指令值(锚点名)必须在链接与锚点间一一对应:链接通过getElementsByName查找目标锚点,锚点通过name属性与隐藏<a>的hash参与匹配,名字不一致将导致滚动定位失败;
  • 局部滚动记得添加scrollTarget类名:该类名同时控制滚动容器选取、scrollTop计算方式与侧边导航定位策略;不添加则默认走整页(window)滚动逻辑;
  • URL Hash 会被同步更新:滚动命中锚点或点击链接后,组件通过history.replaceState写入#锚点名,不会产生历史记录,便于在刷新/分享后仍能感知当前位置;
  • 激活态类名是样式定制的扩展点:可依据anchor-active-by-anchor-link、anchor-active-by-scroll等类名(见上文表格)为不同触发来源编写差异化样式;
  • 当前实现说明:从 d-anchor.ts 与 d-anchor-link.ts 的binding接口看,目前源码仅消费value(锚点名),文档中列出的可选参数anchorActive尚未在指令挂载逻辑中体现,使用前建议先在目标环境中验证或自行扩展,且该组件在 index.ts 中标注状态为50%;
  • 样式依赖主题变量:anchor.scss大量使用--devui-brand、--devui-brand-active、--devui-text-weak、--devui-line等 DevUI Design 变量(引入自@devui/theme/styles-var/devui-var.scss),使用前需确保项目已接入 devui-theme 主题体系,以保证配色与整体设计语言一致。

综上,vue-devui 的 Anchor 组件以「容器 + 链接 + 锚点」三段式指令模型,覆盖了从点击平滑滚动、滚动激活高亮到 URL Hash 同步的完整页内导航链路;其源码结构清晰、样式挂件独立,既可直接用于文档站与工具类页面的章节导航,也为二次定制(激活类名、侧边栏定位策略、滚动节流等)保留了充足的扩展空间。

  • 前端
  • UI组件
  • 设计系统

【免费下载链接】vue-devui

基于全新 DevUI Design 设计体系的 Vue3 组件库,面向研发工具的开源前端解决方案。

项目地址:https://gitcode.com/DevCloudFE/vue-devui
点击查看免费下载

相关推荐

上一篇:gh_mirrors/as/assert在微服务架构中的应用:确保服务间数据交换安全
下一篇:yuzu模拟器终极指南:在电脑上畅玩Switch游戏的完整解决方案

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 1:58:42

tldr 中的 `jira sprint` 命令:在 Jira 项目板上管理冲刺的实战指南

文档教程知识库 【免费下载链接】tldr Collaborative cheatsheets for console commands &#x1f4da;. 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/tl/tldr 点击查看 免费下载 这是一篇以 tldr 仓库孟加拉语页面 pages.bn/common/jira-sprint.md 为核心的技…

作者头像 李华