分步表单 和 自定义表单控件
结合前面所了解到的内容。这里分步分三个路由来实现。
先创建一个store的module。保存我们需要数据,然后引入到store的index.js中
form.js
1 import router from "../../router"; 2 import request from "../../utils/request"; 3 import { notification } from "ant-design-vue"; 4 5 const state = { 6 step: { 7 payAccount: "12345", 8 receiverAccount: { 9 type: "bank", 10 number: "" 11 } 12 } 13 }; 14 15 const actions = { 16 async submitStepForm({ commit }, payload) { 17 if (payload.payload.password == 123123) { 18 let res = await request({ 19 url: "api/form", 20 method: "POST", 21 data: payload.payload 22 }); 23 if (res.data.message == "成功") { 24 commit("saveStepFormData", payload); 25 router.push("/form/step-from/result"); 26 } 27 } else { 28 notification.error({ 29 message: "密码错误" 30 }); 31 } 32 } 33 }; 34 35 const mutations = { 36 saveStepFormData(state, { payload }) { 37 state.step = { 38 ...state.step, 39 ...payload 40 }; 41 } 42 }; 43 export default { 44 namespaced: true, 45 state, 46 actions, 47 mutations 48 };
这里的request也是用的之前的js函数模拟数据。
function form(method) { let res = null; switch (method) { case "POST": res = { message: "成功" }; break; default: res = null; } return res; } module.exports = form;
写第一步
<template>
<div>
<a-form layout="horizontal" :form="form">
<a-form-item>
<a-form-item
label="付款账户"
:label-col="formItemLayout.labelCol"
:wrapperCol="formItemLayout.wrapperCol"
>
<a-input
v-decorator="['payAccount',{
initialValue:step.payAccount,
rules:[
{required:true,message:'请输入付款账户'}
]
}]"
placeholder="请输入内容"
/>
</a-form-item>
<a-form-item
label="收款账户"
:label-col="formItemLayout.labelCol"
:wrapperCol="formItemLayout.wrapperCol"
>
<ReceiverAccount
v-decorator="['receiverAccount',{
initialValue:step.receiverAccount,
rules:[
{required:true,message:'请输入收款账户',
validator: (rule,value,callback) => {
if(value && value.number){
callback()
} else {
callback(false)
}
}}
]
}]"
placeholder="请输入内容"
/>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSubmit">下一步</a-button>
</a-form-item>
</a-form-item>
</a-form>
</div>
</template>
<script>
import ReceiverAccount from "@/components/ReceiverAccount";
export default {
data() {
this.form = this.$form.createForm(this);
return {
formItemLayout: {
labelCol: { span: 4 },
wrapperCol: { span: 14 }
}
};
},
components: {
ReceiverAccount
},
computed: {
step() {
return this.$store.state.form.step;
}
},
methods: {
handleSubmit() {
const { form, $router, $store } = this;
form.validateFields((err, values) => {
if (!err) {
$store.commit({
type: "form/saveStepFormData",
payload: values
});
$router.push("/form/step-from/comfirm");
}
});
}
}
};
</script>
<style></style>
第二步
<template>
<div>
<a-form layout="horizontal" :form="form">
<a-form-item>
<a-form-item
label="付款账户"
:label-col="formItemLayout.labelCol"
:wrapperCol="formItemLayout.wrapperCol"
>{{step.payAccount}}</a-form-item>
<a-form-item
label="收款账户"
:label-col="formItemLayout.labelCol"
:wrapperCol="formItemLayout.wrapperCol"
>
<span style="color:#a12221">{{step.receiverAccount.type == 'alipay'? '支付宝' : '银行卡'}}</span>
<span>: {{step.receiverAccount.number}}</span>
</a-form-item>
<a-form-item
label="账户密码"
:label-col="formItemLayout.labelCol"
:wrapperCol="formItemLayout.wrapperCol"
>
<a-input
type="password"
v-decorator="['password',{
rules:[
{required:true,message:'请输入付款账户密码'}
]
}]"
placeholder="请输入内容"
/>
</a-form-item>
<a-form-item>
<a-button style="margin-right:15px" type="dashed" @click="handleBack">上一步</a-button>
<a-button type="primary" @click="handleSubmit">提交</a-button>
</a-form-item>
</a-form-item>
</a-form>
</div>
</template>
<script>
export default {
data() {
this.form = this.$form.createForm(this);
return {
formItemLayout: {
labelCol: { span: 4 },
wrapperCol: { span: 14 }
}
};
},
computed: {
step() {
console.log(this.$store.state.form.step);
return this.$store.state.form.step;
}
},
methods: {
handleSubmit() {
const { form, $store, step } = this;
form.validateFields((err, values) => {
if (!err) {
$store.dispatch({
type: "form/submitStepForm",
payload: { ...step, ...values }
});
}
});
},
handleBack() {
this.$router.push("/form/step-from/info");
}
}
};
</script>
<style></style>
第三步
<template>
<div>
<h3>操作成功,预计两小时内到账</h3>
<div>{{time}}秒后将自动返回首页</div>
</div>
</template>
<script>
export default {
data() {
return {
time: 3
};
},
mounted() {
var timer = setInterval(() => {
this.time--;
if (this.time <= 0) {
clearInterval(timer);
this.$router.replace("/form/step-from/info");
}
}, 1000);
}
};
</script>
<style></style>
效果图:

在第一步中,有使用到自定义组件,插入到表单中,并且使用了表单自动校验。在antd的官网上,有相关的解释。
自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:
- 提供受控属性
value或其它与valuePropName-参数) 的值同名的属性。 - 提供
onChange事件或trigger-参数) 的值同名的事件。 - 不能是函数式组件。
组件的代码
<template>
<div>
<a-input-group compact>
<a-select v-model="type" style="width :130px" @change="handleTypeChange">
<a-select-option value="alipay">支付宝</a-select-option>
<a-select-option value="bank">银行卡</a-select-option>
</a-select>
<a-input
v-model="number"
style=" calc(100% - 130px)"
@change="handleInputChange"
placeholder="请输入账户"
/>
</a-input-group>
</div>
</template>
<script>
export default {
props: {
value: {
type: Object
}
},
data() {
const { type, number } = this.value || {};
return {
type: type || "alipay",
number: number || ""
};
},
watch: {
value(val) {
Object.assign(this, val);
}
},
methods: {
handleTypeChange(val) {
this.$emit("change", { ...this.value, type: val });
},
handleInputChange(e) {
this.$emit("change", { ...this.value, number: e.target.value });
}
}
};
</script>
<style>
</style>