vue学习笔记14

会有一股神秘感。 提交于 2020-03-30 03:10:31

分步表单 和 自定义表单控件

结合前面所了解到的内容。这里分步分三个路由来实现。

先创建一个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="width: 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>

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!