分步表单 和 自定义表单控件
结合前面所了解到的内容。这里分步分三个路由来实现。
先创建一个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>