☰
Varlet IndexAnchor 索引锚点组件使用指南:API 详解与源码原理剖析
2026/10/14 17:58:09 网站建设 项目流程
  • UI组件
  • 前端

【免费下载链接】varlet

A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.

项目地址:https://gitcode.com/gh_mirrors/va/varlet
点击查看免费下载

导读

IndexAnchor(索引锚点)是 Varlet 索引导航体系中的核心单元组件,配合IndexBar使用,用于为页面中的分组内容标记跳转位置,实现“点击右侧索引字符,快速定位到指定锚点”的典型移动端交互。本文基于 IndexAnchor 官方文档,完整继承其属性与插槽 API,并结合仓库源码、示例与测试用例,带你掌握IndexAnchor的声明式用法、与IndexBar的联动机制以及底层实现原理。

组件定位:IndexBar 体系中的锚点单元

在 Varlet 组件库中,IndexBar与IndexAnchor是一对必须搭配使用的组件:

  • IndexBar负责渲染右侧的锚点索引列表、监听滚动、计算当前高亮项并执行滚动跳转;
  • IndexAnchor负责声明页面中的“锚点位置”,每个IndexAnchor通过index属性声明自己的索引字符(如字母A、B…),并向父级IndexBar注册自身。

从源码看,这种约束是强制的。provide.ts 中useIndexBar()通过useParent按INDEX_BAR_BIND_INDEX_ANCHOR_KEY寻找父级 Provider,并在找不到父组件时直接断言报错:

assert(!!bindParent, 'IndexAnchor', 'You should use this component in "IndexBar"')

也就是说,IndexAnchor脱离IndexBar单独使用会抛出“必须在 IndexBar 中使用”的提示,这是组件设计的硬性前提。

完整 API 参考

以下 API 表格完整继承自 IndexAnchor 官方文档,并补充了源码级说明。

属性

参数说明类型默认值
index索引字符number|string-
  • index是IndexAnchor唯一的属性,同时也是必传属性,用于标识当前锚点的索引字符。
  • 类型声明见 types/indexAnchor.d.ts:index: string | number,支持字母(如A)也支持数字索引。
  • 对应运行时 props 定义见 props.ts:index: [Number, String],即运行时校验同样接受数字与字符串两种类型,且无默认值。

插槽

名称说明参数
default自定义索引字符-

default插槽用于自定义锚点上展示的索引字符内容。若未传入插槽内容,则默认展示index属性的值(详见下文源码分析)。

从使用出发:IndexBar + IndexAnchor 完整示例

IndexAnchor的实际价值体现在与IndexBar的组合使用中。以下示例继承自 IndexBar 官方文档 的基本使用章节:页面按 26 个字母分组,每组放置一个IndexAnchor锚点,点击右侧索引栏即可跳转到对应分组。

<script setup> import { ref, onMounted } from 'vue' const list = ref([]) function handleChange(value) { console.log(value) } onMounted(() => { for (let i = 0; i < 26; i++) { list.value.push(String.fromCharCode(65 + i)) } }) </script> <template> <var-index-bar duration="300" @change="handleChange"> <div v-for="item in list" :key="item"> <var-index-anchor :index="item" class="anchor"> 标题 {{ item }} </var-index-anchor> <var-cell>{{ item }} 文本</var-cell> <var-cell>{{ item }} 文本</var-cell> </div> </var-index-bar> </template> <style> .anchor { height: 42px; display: flex; align-items: center; padding: 0 12px; transition: all 0.25s; background: var(--color-primary); color: #fff; } </style>

仓库中的真实示例 index.vue 与上述用法一致,并在移动端页面中额外传入了sticky-offset-top="54"(配合吸顶的导航栏高度)以及@change事件监听:

<var-index-bar duration="300" :sticky-offset-top="54" @change="handleChange"> <!-- 26 个字母锚点,每个锚点下方挂两组 var-cell --> </var-index-bar>

使用要点总结:

  1. IndexAnchor必须直接或间接嵌套在IndexBar内部;
  2. 每个锚点的index值需与右侧索引列表中的字符一一对应;
  3. 锚点本身可以像普通块级元素一样自由设置样式(高度、背景、内边距等),吸顶后依然生效。

源码实现:IndexAnchor 如何工作

渲染逻辑:吸顶能力来自 Sticky

查看 IndexAnchor.vue 的模板可以发现,IndexAnchor本身并不实现吸顶逻辑,而是通过动态组件选择渲染容器:

<component :is="sticky ? n('$-sticky') : Transition" ref="anchorEl" :offset-top="sticky ? stickyOffsetTop : null" :z-index="sticky ? zIndex : null" :disabled="disabled && !cssMode" :css-mode="cssMode" > <div :class="n()" v-bind="$attrs"> <slot>{{ name }}</slot> </div> </component>
  • 当父级IndexBar的sticky为true(默认值)时,外层渲染为 Varlet 的Sticky吸顶容器,锚点滚动到顶部后自动吸顶;
  • 当sticky为false时,退化为普通的Transition包裹;
  • stickyOffsetTop、zIndex、cssMode等全部由父级IndexBar通过 Provider 注入(见 provide.ts);
  • 内部根节点为var-index-anchor的div,通过<slot>{{ name }}</slot>展示索引字符,其中name是props.index的计算值。

注册机制:向 IndexBar 暴露能力

每个IndexAnchor在setup阶段构造一个IndexAnchorProvider并注册到父级(IndexAnchor.vue):

const indexAnchorProvider: IndexAnchorProvider = { index, name, setDisabled, getOffsetTop, } bindIndexBar(indexAnchorProvider)

接口定义见 provide.ts:

  • index:锚点在子列表中的序号;
  • name:索引字符(props.index);
  • setDisabled:由 IndexBar 在滚动计算时控制当前锚点的吸顶开关;
  • getOffsetTop:读取锚点元素距离父级滚动容器顶部的偏移量,用于滚动位置计算(兼容组件实例与原生元素两种形态,见 IndexAnchor.vue)。

安装与类型导出

IndexAnchor 入口文件 与其他 Varlet 组件保持一致:

withInstall(IndexAnchor) withPropsDefaultsSetter(IndexAnchor, indexAnchorProps) export { indexAnchorProps } export const _IndexAnchorComponent = IndexAnchor

withInstall负责挂载到app.component,withPropsDefaultsSetter负责将默认值同步到组件实例,同时对外暴露indexAnchorProps供按需引入与类型推导使用。

与 IndexBar 的联动机制:滚动高亮与点击跳转

理解了IndexAnchor的注册机制后,再看 IndexBar.vue 是如何消费这些锚点的:

  1. 收集锚点:IndexBar通过useIndexAnchors()收集所有子级IndexAnchor,并watch锚点数量,在doubleRaf后生成右侧索引列表anchorNameList(IndexBar.vue)。
  2. 滚动计算高亮:handleScroll遍历每个锚点,用getOffsetTop()计算其与当前滚动位置的距离,命中区间后调用anchor.setDisabled(false)并触发emitEvent(anchor),更新active并派发change事件(IndexBar.vue)。
  3. 点击跳转:点击右侧索引项时,anchorClick找到对应锚点,计算目标滚动位置,通过easeInOutCubic缓动函数配合duration(默认0)执行平滑滚动(IndexBar.vue)。
  4. 实例方法scrollTo:通过 ref 调用scrollTo(index, options)可编程式跳转到指定锚点;其中options.event: false可阻止change事件的触发(IndexBar.vue)。

也就是说,IndexAnchor的getOffsetTop、setDisabled是整条联动链路上最关键的“数据接口”,IndexAnchor的吸顶、高亮、跳转能力全部建立在父级对其状态的管理之上。

测试验证:API 行为有据可查

IndexBar 测试用例 对IndexAnchor的协作行为给出了直接验证:

  • 组件可独立安装注册:app.use(IndexBar).use(IndexAnchor)后两个组件均可正常注册(index.spec.js#L88-L93);
  • sticky 开关:sticky: false时锚点外层不再渲染.var-sticky(index.spec.js#L96-L108);
  • stickyOffsetTop:传入'36px'后吸顶容器样式包含top: 36px(index.spec.js#L110-L124);
  • hideList:hideList: true时右侧索引列表display: none(index.spec.js#L126-L144);
  • zIndex 与 highlightColor:z-index随属性更新,高亮项颜色可自定义为purple(index.spec.js#L146-L173);
  • 事件与方法:点击索引项触发click事件并使对应项高亮;scrollTo('A')可将高亮切到A;滚动到锚点区间触发change事件(index.spec.js#L176-L225)。

这些测试同时覆盖了IndexAnchor的注册、吸顶、偏移与高亮协作,可作为实现行为的权威依据。

样式定制

IndexAnchor锚点自身的样式可通过外层传入的 class/style 自由定制;右侧索引列表的样式则由IndexBar提供 CSS 变量控制(定义见 indexBar.less),可用 StyleProvider 组件 进行全局定制:

变量名默认值
--index-bar-list-right0
--index-bar-list-top50%
--index-bar-list-leftauto
--index-bar-list-bottomauto
--index-bar-list-transformtranslate(0, -50%)
--index-bar-list-item-font-sizevar(--font-size-xs)
--index-bar-list-item-colorvar(--color-primary)
--index-bar-list-item-active-colorvar(--color-danger)
--index-bar-list-item-height14px
--index-bar-list-item-padding0 10px

总结

IndexAnchor虽然 API 极简(仅index属性与default插槽),但在 Varlet 索引导航体系中承担着锚点声明、位置上报与吸顶呈现的关键职责。实际使用时请牢记:它必须与IndexBar组合,通过index建立字符映射,配合sticky、sticky-offset-top、duration、scrollTo等能力即可快速搭建通讯录、城市列表等字母索引场景。如需深入理解联动细节,可继续阅读 IndexAnchor.vue、IndexBar.vue 与 index.spec.js 三份核心文件。

  • UI组件
  • 前端

【免费下载链接】varlet

A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.

项目地址:https://gitcode.com/gh_mirrors/va/varlet
点击查看免费下载

相关推荐

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询