Vant Steps 步骤条组件完全指南:状态机制、API 配置与主题定制
【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant
导读
Steps是 Vant 移动端组件库中用于展示操作流程的步骤条组件,它把“买家下单 → 商家接单 → 买家提货 → 交易完成”这类流程拆解为带状态的可视化节点,帮助用户实时了解当前操作在整体流程中的位置。本指南以 Steps 官方文档 为骨架,结合 Vant 仓库内Steps与Step两个组件的源码实现、演示用例与测试用例,系统讲解组件的引入方式、基础用法、状态判定原理、完整 API、插槽体系与 CSS 变量主题定制,读完即可在真实业务中正确使用并深度定制步骤条。
组件介绍与引入
什么是 Steps 步骤条
步骤条用于将一项复杂操作拆解为若干连续环节,让用户明确“现在进行到哪一步、还剩几步”。在 Vant 中它由两个组件协作完成:
Steps:外层容器,负责接收active、direction等全局配置;Step:内层节点,每个van-step渲染一个步骤,状态由Steps根据索引统一推导。
在 Steps.tsx 中,外层组件通过useChildren建立与子节点Step的关联,并把自身props与onClickStep回调下发给每个子步骤,从而实现“父组件统管状态、子组件自主渲染”的协作模型。
引入方式
通过以下方式来全局注册组件,更多注册方式可参考 组件注册文档:
import { createApp } from 'vue'; import { Step, Steps } from 'vant'; const app = createApp(); app.use(Step); app.use(Steps);从源码看,Steps与Step都通过withInstall包装导出,并声明了VanSteps、VanStep全局组件类型(见 steps/index.ts 与 step/index.ts),因此注册后即可在模板中使用<van-steps>、<van-step>标签。
基础用法
active属性表示当前步骤的索引,从 0 起计。以下示例中active = 1,表示第 2 个步骤“商家接单”为进行中状态:
<van-steps :active="active"> <van-step>买家下单</van-step> <van-step>商家接单</van-step> <van-step>买家提货</van-step> <van-step>交易完成</van-step> </van-steps>import { ref } from 'vue'; export default { setup() { const active = ref(1); return { active }; }, };状态是如何推导的:三步状态机
在 Step.tsx 中,每个步骤的状态完全由“自身索引”与“父组件的 active”比较得出:
const getStatus = () => { const active = +parentProps.active; if (index.value < active) { return 'finish'; // 已完成 } return index.value === active ? 'process' : 'waiting'; // 进行中 / 待处理 };即每个van-step只会处于三种状态之一:
| 状态 | 判定条件 | 视觉表现 |
|---|---|---|
finish(已完成) | index < active | 连接线与节点使用完成态颜色(默认主色) |
process(进行中) | index === active | 节点显示激活图标(默认对勾checked) |
waiting(待处理) | index > active | 节点显示未激活图标或灰色圆点 |
此外active支持传入number | string(源码中使用makeNumericProp(0)声明),字符串数字会被自动转换比较,这在从接口拿到字符串索引时非常实用。
带“下一步”按钮的完整交互
仓库自带的 demo/index.vue 展示了真实业务中的典型联动——用按钮推进步骤:
<script setup lang="ts"> import { ref } from 'vue'; const active = ref(1); const nextStep = () => { active.value = ++active.value % 4; }; </script> <template> <van-steps :active="active"> <van-step>买家下单</van-step> <van-step>商家接单</van-step> <van-step>买家提货</van-step> <van-step>交易完成</van-step> </van-steps> <van-button @click="nextStep">下一步</van-button> </template>active取模循环,4 步走完会重新回到第一步,适合订单状态循环演示场景。
自定义样式:图标与颜色
可以通过active-icon和active-color属性设置激活状态下的图标和颜色:
<van-steps :active="active" active-icon="success" active-color="#07c160"> <van-step>买家下单</van-step> <van-step>商家接单</van-step> <van-step>买家提货</van-step> <van-step>交易完成</van-step> </van-steps>图标渲染优先级(源码级拆解)
从 Step.tsx 的renderCircle可以看到节点图标的完整渲染优先级:
- 进行中(process):优先渲染
active-icon插槽,否则渲染<Icon name={activeIcon}>,颜色使用activeColor; - 已完成(finish):仅当配置了
finishIcon或finish-icon插槽时才渲染自定义完成图标(优先级高于inactive-icon),否则继续走下面的未激活分支; - 未激活/兜底:优先
inactive-icon插槽,其次渲染inactiveIcon图标,若都未配置则渲染一个纯 CSS 的圆点<i class="van-step__circle">(圆点颜色由连接线当前状态决定)。
同时,完成态连接线颜色通过lineStyle动态注入:状态为finish时使用activeColor,否则使用inactiveColor;标题文字颜色也按 process/waiting 状态分别取activeColor/inactiveColor。这解释了为什么active-color会同时影响“当前步骤和已完成步骤”的视觉。
竖向步骤条
可以通过设置direction属性把步骤条从水平改为垂直方向,常用于物流详情、审批流等需要展示时间与描述信息的场景:
<van-steps direction="vertical" :active="0"> <van-step> <h3>【城市】物流状态1</h3> <p>2016-07-12 12:40</p> </van-step> <van-step> <h3>【城市】物流状态2</h3> <p>2016-07-11 10:00</p> </van-step> <van-step> <h3>快件已发货</h3> <p>2016-07-10 09:30</p> </van-step> </van-steps>竖向模式在样式层通过 step/index.less 中的.van-step--vertical实现:步骤改为块级布局、float: none,连接线变为左侧 1px 的竖直长线,节点圆点/图标定位于左侧居中;外层.van-steps--vertical(见 steps/index.less)则增加了左侧内边距为图标留位。两个方向都保证了最后一个步骤的连接线宽度为 0,不会出现多余的“尾巴”。
点击步骤与事件
Steps支持点击步骤的标题或图标区域时触发click-step事件,回调参数为被点击步骤的索引index: number:
<van-steps :active="active" @click-step="onClickStep"> <van-step>买家下单</van-step> <van-step>商家接单</van-step> </van-steps>function onClickStep(index) { active.value = index; // 点击跳转到对应步骤 console.log('当前点击了第', index, '步'); }点击如何从子节点回传父组件
事件链路依赖父子组件通信:在 Steps.tsx 中,父组件定义onClickStep = (index) => emit('clickStep', index)并通过linkChildren注入;子组件 Step.tsx 在标题(.van-step__title)和节点容器(.van-step__circle-container)上都绑定了onClick,点击时调用parent.onClickStep(index.value)。
steps/test/index.spec.tsx 中的测试精确验证了这一行为:
wrapper.find('.van-step__title').trigger('click'); expect(onClickStep).toHaveBeenCalledWith(0); wrapper.findAll('.van-step__circle-container')[2].trigger('click'); expect(onClickStep).toHaveBeenLastCalledWith(2);测试还验证了点击步骤容器本身(非标题、非图标区域)不会触发事件,说明事件只绑定在可交互区域上。
API 详解
Steps Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| active | 当前步骤对应的索引值 | number | string | 0 |
| direction | 步骤条方向,可选值为vertical | string | horizontal |
| active-icon | 当前步骤对应的底部图标,可选值见 Icon 组件 | string | checked |
| inactive-icon | 非当前步骤对应的底部图标,可选值见 Icon 组件 | string | - |
| finish-icon | 已完成步骤对应的底部图标,优先级高于inactive-icon,可选值见 Icon 组件 | string | - |
| active-color | 当前步骤和已完成步骤的颜色 | string | #1989fa |
| inactive-color | 未激活步骤的颜色 | string | #969799 |
| icon-prefix | 图标类名前缀,等同于 Icon 组件的 class-prefix 属性 | string | van-icon |
对照源码 Steps.tsx 中的stepsProps声明,可补充以下实现细节:
active使用makeNumericProp(0)声明,同时接受数字与数字字符串;direction使用makeStringProp('horizontal')声明,可选值即StepsDirection联合类型'horizontal' | 'vertical';iconPrefix会被透传给内部<Icon>的classPrefix,默认van-icon,用于自定义图标库时替换类名前缀。测试should render icon-prefix correctly验证了传入iconPrefix="custom-icon"后渲染为van-icon-custom-icon前缀的类名;activeColor、inactiveColor未设置默认值,实际生效默认色来自 CSS 变量层(--van-primary-color对应#1989fa、--van-gray-6对应#969799)。
Step Slots
| 名称 | 说明 |
|---|---|
| default | 步骤内容 |
| active-icon | 自定义激活状态图标 |
| inactive-icon | 自定义未激活状态图标 |
| finish-icon | 自定义已完成步骤对应的底部图标,优先级高于inactive-icon |
插槽使用示例(可传入任意自定义内容,如自定义 SVG 图标):
<van-steps :active="1"> <van-step> <template #active-icon> <van-icon name="success" color="#07c160" /> </template> <template #finish-icon> <van-icon name="passed" color="#1989fa" /> </template> <template #inactive-icon> <van-icon name="circle" color="#969799" /> </template> 买家下单 </van-step> </van-steps>steps/test/index.spec.tsx 中should render icon slot correctly与should render finish icon slot correctly两个用例分别验证了active-icon/inactive-icon/finish-icon插槽的渲染结果,说明插槽方案与属性方案并存且插槽优先级更高。
Steps Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| click-step | 点击步骤的标题或图标时触发 | index: number |
类型定义
组件导出以下类型定义,可在 TypeScript 项目中获得完整的类型提示:
import type { StepsProps, StepsDirection } from 'vant';相关类型的源码定义位置:
StepsProps:由stepsProps通过ExtractPropTypes推导(Steps.tsx);StepsDirection:'horizontal' | 'vertical'字面量联合类型(同上);StepsThemeVars:主题变量类型{ stepsBackground?: string }(types.ts)。
以上类型均在 index.ts 中统一 re-export。
主题定制:CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。推荐配合 ConfigProvider 组件 在应用层统一覆盖:
| 名称 | 默认值 | 描述 |
|---|---|---|
| --van-step-text-color | var(--van-text-color-2) | 步骤文字颜色 |
| --van-step-active-color | var(--van-primary-color) | 激活状态颜色 |
| --van-step-process-text-color | var(--van-text-color) | 进行中步骤文字颜色 |
| --van-step-font-size | var(--van-font-size-md) | 步骤字体大小 |
| --van-step-line-color | var(--van-border-color) | 连接线颜色 |
| --van-step-finish-line-color | var(--van-primary-color) | 已完成连接线颜色 |
| --van-step-finish-text-color | var(--van-text-color) | 已完成步骤文字颜色 |
| --van-step-icon-size | 12px | 步骤图标大小 |
| --van-step-circle-size | 5px | 圆点直径 |
| --van-step-circle-color | var(--van-gray-6) | 圆点颜色 |
| --van-step-horizontal-title-font-size | var(--van-font-size-sm) | 水平方向标题字体大小 |
| --van-steps-background | var(--van-background-2) | 步骤条背景色 |
提示:以上变量分为两组定义——
--van-step-*系列定义在 step/index.less 的:root, :host中,--van-steps-background定义在 steps/index.less 中,两者都可以通过 ConfigProvider 或:root覆盖。
使用示例(全局覆盖为绿色主题):
<van-config-provider :theme-vars="{ stepActiveColor: '#07c160', stepFinishLineColor: '#07c160', }" > <van-steps :active="1"> <van-step>买家下单</van-step> <van-step>商家接单</van-step> </van-steps> </van-config-provider>小结
Steps 组件麻雀虽小五脏俱全:外层Steps通过useChildren统一管理active索引并向下分发配置,内层Step依据“索引与 active 的大小关系”自动推导finish / process / waiting三态;图标渲染遵循“插槽 > 属性 > CSS 圆点兜底”的优先级,click-step事件只绑定在标题与节点可点击区域。结合本文给出的 演示代码、源码实现 与 测试用例,开发者可以放心地将步骤条用于订单跟踪、表单分步引导、物流详情等移动端场景,并通过 Props、插槽与 CSS 变量三层机制完成灵活定制。
【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考