更新记录
1.0.0(2025-10-23) 下载此版本
更新日志
v1.0.0 (2025-10-23)
新增功能
- ✨ 多步骤表单向导组件
- ✨ 可自定义步骤条和步骤内容
- ✨ 支持水平/垂直两种步骤条方向
- ✨ 提供上一步、下一步、提交等操作按钮
- ✨ 支持表单数据管理
- ✨ 提供丰富的插槽自定义能力
- ✨ 增加步骤点击跳转功能(可配置 clickable 属性)
- ✨ 增加步骤切换动画效果
- ✨ 新增 beforeChange 钩子函数,支持步骤切换前的验证
- ✨ 新增按钮禁用状态和加载状态
- ✨ 新增表单验证功能和工具函数库
- ✨ 新增步骤管理器(StepsManager)类
- ✨ 完整的 TypeScript 类型定义
- ✨ 完善 nvue 版本的组件实现
- ✨ 新增常用验证规则(用户名、密码、邮箱、手机号等)
- ✨ 支持自定义步骤图标
- ✨ 支持错误状态显示
平台兼容性
uni-app(3.6.11)
| Vue2 | Vue2插件版本 | Vue3 | Vue2插件版本 | Chrome | Chrome插件版本 | Safari | Safari插件版本 | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | 5.0 | 1.0.0 | 12 | 1.0.0 | √ | 1.0.0 |
| 微信小程序 | 微信小程序插件版本 | 支付宝小程序 | 支付宝小程序插件版本 | 抖音小程序 | 抖音小程序插件版本 | 百度小程序 | 百度小程序插件版本 | 快手小程序 | 快手小程序插件版本 | 京东小程序 | 京东小程序插件版本 | 鸿蒙元服务 | 鸿蒙元服务插件版本 | QQ小程序 | QQ小程序插件版本 | 飞书小程序 | 飞书小程序插件版本 | 快应用-华为 | 快应用-华为插件版本 | 快应用-联盟 | 快应用-联盟插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 |
uni-app x(3.6.11)
| Chrome | Chrome插件版本 | Safari | Safari插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 | 微信小程序 | 微信小程序插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | 5.0 | 1.0.0 | 12 | 1.0.0 | √ | 1.0.0 | √ | 1.0.0 |
hy-steps-form 多步骤表单向导
简介
hy-steps-form 是一个功能强大、灵活易用的多步骤表单向导组件,专为 uni-app 开发。支持自定义步骤内容、表单验证、步骤跳转等功能,适用于用户注册、信息填写、订单提交等多步骤流程场景。
特性
- ✨ 灵活的步骤管理 - 支持水平/垂直布局,可自定义步骤数量
- 🎨 高度可定制 - 支持自定义颜色、文字、图标等
- 📝 完善的表单验证 - 内置常用验证规则,支持自定义验证
- 🔄 步骤跳转 - 支持点击步骤条跳转(可配置)
- 🎯 状态管理 - 支持等待、进行中、完成、错误等状态
- 💫 过渡动画 - 步骤切换支持流畅的过渡动画
- 🔌 钩子函数 - 提供 beforeChange 钩子,方便进行验证和拦截
- 📱 全平台支持 - 支持 H5、小程序、App(含 nvue)
- 🎁 工具函数库 - 提供步骤管理器和验证工具函数
- 📦 TypeScript 支持 - 完整的 TypeScript 类型定义
安装
方式一:通过 uni_modules 安装(推荐)
- 在 DCloud 插件市场 搜索
hy-steps-form - 点击"导入插件"或"下载插件"
- 导入到 HBuilderX 项目中
方式二:手动下载
- 下载插件压缩包
- 解压到项目的
uni_modules目录下
快速开始
基础用法
<template>
<view class="container">
<hy-steps-form
:current="currentStep"
:steps="steps"
@change="onStepChange"
@submit="onSubmit"
>
<!-- 步骤1 -->
<template v-slot:step0>
<view class="form-section">
<text class="label">姓名</text>
<input v-model="form.name" placeholder="请输入姓名" />
</view>
</template>
<!-- 步骤2 -->
<template v-slot:step1>
<view class="form-section">
<text class="label">手机号</text>
<input v-model="form.phone" type="number" placeholder="请输入手机号" />
</view>
</template>
<!-- 步骤3 -->
<template v-slot:step2>
<view class="form-section">
<text class="label">确认信息</text>
<view class="info-item">
<text>姓名:{{ form.name }}</text>
</view>
<view class="info-item">
<text>手机:{{ form.phone }}</text>
</view>
</view>
</template>
</hy-steps-form>
</view>
</template>
<script>
export default {
data() {
return {
currentStep: 0,
steps: [
{ title: '个人信息', description: '填写基本信息' },
{ title: '联系方式', description: '填写联系方式' },
{ title: '确认信息', description: '确认并提交' }
],
form: {
name: '',
phone: ''
}
};
},
methods: {
onStepChange(step) {
this.currentStep = step;
},
onSubmit(data) {
console.log('提交表单:', this.form);
uni.showToast({
title: '提交成功!',
icon: 'success'
});
}
}
};
</script>
<style>
.container {
padding: 20px;
}
.form-section {
padding: 20px;
}
.label {
font-size: 14px;
color: #333;
margin-bottom: 10px;
}
.info-item {
padding: 10px 0;
border-bottom: 1px solid #eee;
}
</style>
带验证的表单
<template>
<view>
<hy-steps-form
:current="currentStep"
:steps="steps"
:before-change="handleBeforeChange"
:next-disabled="nextDisabled"
@change="onStepChange"
@submit="onSubmit"
>
<template v-slot:step0="{ setFormData }">
<view class="form-section">
<input
v-model="form.username"
placeholder="请输入用户名(4-20位)"
@input="setFormData({ username: form.username })"
/>
<text v-if="errors.username" class="error">{{ errors.username }}</text>
</view>
</template>
<template v-slot:step1="{ setFormData }">
<view class="form-section">
<input
v-model="form.email"
placeholder="请输入邮箱"
@input="setFormData({ email: form.email })"
/>
<text v-if="errors.email" class="error">{{ errors.email }}</text>
</view>
</template>
<template v-slot:step2>
<view class="form-section">
<text>用户名:{{ form.username }}</text>
<text>邮箱:{{ form.email }}</text>
</view>
</template>
</hy-steps-form>
</view>
</template>
<script>
import { validateForm, commonValidations } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
export default {
data() {
return {
currentStep: 0,
steps: [
{ title: '账号信息' },
{ title: '邮箱验证' },
{ title: '完成注册' }
],
form: {
username: '',
email: ''
},
errors: {},
nextDisabled: false,
// 每个步骤的验证规则
validationSchemas: {
0: { username: commonValidations.username },
1: { email: commonValidations.email }
}
};
},
methods: {
onStepChange(step) {
this.currentStep = step;
this.errors = {};
},
// 步骤切换前的验证
async handleBeforeChange(targetStep, currentStep, formData) {
// 如果是往后跳转,需要验证当前步骤
if (targetStep > currentStep || targetStep === -1) {
const schema = this.validationSchemas[currentStep];
if (schema) {
const { valid, errors } = validateForm(this.form, schema);
if (!valid) {
this.errors = errors;
uni.showToast({
title: Object.values(errors)[0],
icon: 'none'
});
return false;
}
}
}
this.errors = {};
return true;
},
onSubmit(data) {
console.log('提交数据:', data.formData);
uni.showToast({
title: '注册成功!',
icon: 'success'
});
}
}
};
</script>
<style>
.error {
color: #ff4d4f;
font-size: 12px;
margin-top: 5px;
}
</style>
使用步骤管理器
<template>
<view>
<hy-steps-form
ref="stepsForm"
:current="manager.current"
:steps="manager.steps"
:before-change="handleBeforeChange"
@change="onStepChange"
@submit="onSubmit"
/>
</view>
</template>
<script>
import { createStepsManager, commonValidations } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
export default {
data() {
const steps = [
{ title: '基本信息' },
{ title: '详细信息' },
{ title: '确认提交' }
];
const manager = createStepsManager(steps);
// 设置每个步骤的验证规则
manager.setValidationSchema(0, {
name: commonValidations.name,
phone: commonValidations.phone
});
manager.setValidationSchema(1, {
email: commonValidations.email,
idCard: commonValidations.idCard
});
return {
manager
};
},
methods: {
onStepChange(step) {
this.manager.setCurrent(step);
},
async handleBeforeChange(targetStep, currentStep, formData) {
if (targetStep > currentStep || targetStep === -1) {
const { valid, errors } = this.manager.validateCurrentStep();
if (!valid) {
uni.showToast({
title: Object.values(errors)[0],
icon: 'none'
});
return false;
}
}
return true;
},
onSubmit() {
const formData = this.$refs.stepsForm.getFormData();
console.log('提交表单:', formData);
// 提交成功后重置
this.manager.reset();
this.$refs.stepsForm.resetFormData();
}
}
};
</script>
API 文档
Props 属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| current | Number | 0 |
当前步骤索引(从0开始) |
| steps | Array | [] |
步骤配置数组,见下方 StepItem 定义 |
| direction | String | 'horizontal' |
步骤条方向,可选 'horizontal' 或 'vertical' |
| activeColor | String | '#1890ff' |
激活状态颜色 |
| inactiveColor | String | '#ccc' |
未激活状态颜色 |
| showButtons | Boolean | true |
是否显示操作按钮 |
| buttonNextText | String | '下一步' |
下一步按钮文字 |
| buttonPrevText | String | '上一步' |
上一步按钮文字 |
| buttonSubmitText | String | '提交' |
提交按钮文字 |
| clickable | Boolean | false |
是否允许点击步骤条跳转 |
| animation | Boolean | true |
是否开启步骤切换动画 |
| beforeChange | Function | null |
步骤切换前的钩子函数,返回 false 可阻止切换 |
| prevDisabled | Boolean | false |
是否禁用上一步按钮 |
| nextDisabled | Boolean | false |
是否禁用下一步按钮 |
| submitDisabled | Boolean | false |
是否禁用提交按钮 |
| nextLoading | Boolean | false |
下一步按钮加载状态 |
| submitLoading | Boolean | false |
提交按钮加载状态 |
StepItem 定义
interface StepItem {
title: string; // 步骤标题(必填)
description?: string; // 步骤描述
icon?: string; // 步骤图标(支持 emoji 或文字)
status?: 'wait' | 'process' | 'finish' | 'error'; // 步骤状态
}
Events 事件
| 事件名 | 参数 | 说明 |
|---|---|---|
| change | (current: number) |
步骤改变时触发 |
| next | (data: StepChangeData) |
点击下一步时触发 |
| prev | (data: StepChangeData) |
点击上一步时触发 |
| submit | (data: SubmitData) |
点击提交时触发 |
| step-click | (index: number) |
点击步骤条时触发(需要 clickable 为 true) |
| form-change | (formData: Object) |
表单数据改变时触发 |
| validation-error | (data: ValidationErrorData) |
验证失败时触发 |
| validate | (data: ValidateData) |
验证步骤时触发 |
事件参数类型
// 步骤切换事件数据
interface StepChangeData {
current: number; // 当前步骤索引
prev?: number; // 上一个步骤索引
formData: Object; // 表单数据
}
// 提交事件数据
interface SubmitData {
formData: Object; // 表单数据
current: number; // 当前步骤索引
}
// 验证错误事件数据
interface ValidationErrorData {
step: number; // 出错的步骤索引
error: any; // 错误信息
}
Methods 方法
通过 ref 调用组件方法:
// 获取组件实例
const stepsForm = this.$refs.stepsForm;
// 设置表单数据
stepsForm.setFormData({ name: '张三', age: 25 });
// 获取表单数据
const formData = stepsForm.getFormData();
// 重置表单数据
stepsForm.resetFormData();
// 跳转到指定步骤
await stepsForm.goToStep(2);
// 设置步骤状态
stepsForm.setStepStatus(0, 'finish');
stepsForm.setStepStatus(1, 'error');
// 验证当前步骤
await stepsForm.validateStep();
Slots 插槽
| 插槽名 | 作用域 | 说明 |
|---|---|---|
| step{index} | { current, form, setFormData } |
每个步骤的内容插槽,例如 step0、step1 等 |
插槽作用域参数:
current: 当前步骤索引form: 表单数据对象setFormData: 设置表单数据的方法
工具函数库
验证规则
import { validationRules, commonValidations } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
// 必填验证
validationRules.required('此项为必填项')
// 邮箱验证
validationRules.email('请输入正确的邮箱地址')
// 手机号验证
validationRules.phone('请输入正确的手机号')
// 身份证验证
validationRules.idCard('请输入正确的身份证号')
// 最小长度验证
validationRules.minLength(6)('密码不能少于6位')
// 最大长度验证
validationRules.maxLength(20)('用户名不能超过20位')
// 长度范围验证
validationRules.lengthRange(4, 20)('长度必须在4-20位之间')
// 数值范围验证
validationRules.range(1, 100)('数值必须在1-100之间')
// 正则表达式验证
validationRules.pattern(/^[a-zA-Z0-9]+$/)('只能包含字母和数字')
// 自定义验证
validationRules.custom((value) => value !== '123456')('不能使用弱密码')
常用验证规则组合
import { commonValidations } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
// 预定义的常用验证规则
commonValidations.username // 用户名验证(4-20位字母数字下划线)
commonValidations.password // 密码验证(6-20位)
commonValidations.strongPassword // 强密码验证(包含大小写字母和数字)
commonValidations.email // 邮箱验证
commonValidations.phone // 手机号验证
commonValidations.idCard // 身份证验证
commonValidations.name // 姓名验证(2-20位中文或字母)
commonValidations.verifyCode // 验证码验证(4-6位数字)
验证函数
import { validateField, validateForm } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
// 验证单个字段
const error = validateField('test@example.com', [
validationRules.required(),
validationRules.email()
]);
if (error) {
console.log('验证失败:', error);
}
// 验证表单对象
const formData = {
username: 'john',
email: 'john@example.com',
phone: '***'
};
const schema = {
username: commonValidations.username,
email: commonValidations.email,
phone: commonValidations.phone
};
const { valid, errors } = validateForm(formData, schema);
if (!valid) {
console.log('验证失败:', errors);
// errors: { username: '长度不能少于4个字符', ... }
}
步骤管理器
import { createStepsManager } from '@/uni_modules/hy-steps-form/js_sdk/index.js';
// 创建步骤管理器
const manager = createStepsManager([
{ title: '步骤1' },
{ title: '步骤2' },
{ title: '步骤3' }
]);
// 设置当前步骤
manager.setCurrent(1);
// 获取当前步骤
const current = manager.getCurrent(); // 1
// 下一步
manager.next();
// 上一步
manager.prev();
// 跳转到指定步骤
manager.goTo(2);
// 判断是否是第一步/最后一步
manager.isFirst(); // false
manager.isLast(); // true
// 设置表单数据
manager.setFormData({ name: '张三', age: 25 });
// 获取表单数据
const formData = manager.getFormData();
// 重置表单数据
manager.resetFormData();
// 设置步骤验证规则
manager.setValidationSchema(0, {
name: commonValidations.name,
phone: commonValidations.phone
});
// 验证当前步骤
const { valid, errors } = manager.validateCurrentStep();
// 验证所有步骤
const result = manager.validateAllSteps();
// 设置步骤状态
manager.setStepStatus(0, 'finish');
manager.setStepStatus(1, 'error');
// 获取步骤状态
const status = manager.getStepStatus(0);
// 重置所有
manager.reset();
// 获取进度百分比
const progress = manager.getProgress(); // 0-100
高级用法
异步验证
methods: {
async handleBeforeChange(targetStep, currentStep, formData) {
if (targetStep > currentStep) {
// 模拟异步验证(如检查用户名是否已存在)
try {
const res = await uni.request({
url: '/api/check-username',
data: { username: formData.username }
});
if (!res.data.available) {
uni.showToast({
title: '用户名已存在',
icon: 'none'
});
return false;
}
} catch (error) {
console.error('验证失败:', error);
return false;
}
}
return true;
}
}
动态步骤
<template>
<hy-steps-form
:current="currentStep"
:steps="dynamicSteps"
@change="onStepChange"
>
<template v-for="(step, index) in dynamicSteps" :key="index" v-slot:[`step${index}`]>
<view>{{ step.content }}</view>
</template>
</hy-steps-form>
</template>
<script>
export default {
data() {
return {
currentStep: 0,
dynamicSteps: []
};
},
onLoad() {
// 根据业务逻辑动态生成步骤
this.loadSteps();
},
methods: {
async loadSteps() {
// 从服务器获取步骤配置
const res = await uni.request({ url: '/api/get-steps' });
this.dynamicSteps = res.data.steps;
},
onStepChange(step) {
this.currentStep = step;
}
}
};
</script>
自定义样式
<template>
<hy-steps-form
:steps="steps"
active-color="#52c41a"
inactive-color="#d9d9d9"
direction="vertical"
>
<!-- 步骤内容 -->
</hy-steps-form>
</template>
<style>
/* 可以通过 /deep/ 或 ::v-deep 深度选择器自定义样式 */
::v-deep .hy-steps-form {
padding: 20px;
}
::v-deep .steps-content {
background-color: #f5f5f5;
border-radius: 8px;
padding: 20px;
}
::v-deep .btn-next {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
</style>
注意事项
- 插槽命名:步骤插槽需要使用
step0、step1、step2等格式命名,数字从 0 开始 - 步骤索引:current 属性的索引从 0 开始,而不是从 1 开始
- beforeChange 钩子:返回
false或抛出异常可以阻止步骤切换 - nvue 限制:在 nvue 页面中,某些 CSS 样式可能不支持,建议使用行内样式
- 表单数据管理:建议使用组件提供的
setFormData方法来管理表单数据,以便组件能够正确追踪数据变化
常见问题
1. 如何实现步骤跳转?
设置 clickable 属性为 true 即可启用步骤点击跳转功能。
2. 如何在跳转前进行验证?
使用 beforeChange 钩子函数,在函数中进行验证,返回 false 可阻止跳转。
3. 如何自定义按钮文字?
使用 buttonNextText、buttonPrevText、buttonSubmitText 属性自定义按钮文字。
4. 如何隐藏操作按钮?
设置 showButtons 属性为 false,然后可以自定义按钮并调用组件方法。
5. 如何实现提交按钮的加载状态?
设置 submitLoading 属性为 true,配合 @submit 事件使用。
更新日志
查看 CHANGELOG.md
许可证
MIT License
支持
如果这个组件对你有帮助,欢迎 Star ⭐️
如有问题或建议,欢迎提 Issue 或 PR

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 25
赞赏 0
下载 10621756
赞赏 1792
赞赏
京公网安备:11010802035340号