Vue脚手架系列09-表单组件设计-如何正确设计表单校验规则

272 阅读1分钟

1.Input组件的$emit:

🍊代码这里面就不占用太多篇幅了,手字数限制,来说下上一篇中Input组件中的this.$parent.$emit('validate',this.inputVal).,这个调用的是FormItem组件中的validate方法,这个validate方法是在FormItem组件的created生命周期中通过 this.$on("validate",this.validate)来绑定的,这里明白了,有利于理解$emit

2.FormItem组件的逻辑实现:

下面再来明确下FormItem组件需要完成的几件事情:

  • 绑定labelprop属性
  • 获取当前输入框的规则
  • 如果输入框和ruler不匹配,显示错误信息
  • Input组件中,用户输入内容的时候,通知FormItem的做校验(校验的方法)
  • 使用async-validate做校验
//FormItem.vue

<template>
    <div>
         <!--如果有label显示,没有就隐藏 -->
        <label v-if="label">{{label}}</label>
         <!-- 插槽,用于放input组件的-->
        <slot></slot>
        <!-- 显示校验的错误信息-->
        <p v-if="validateStatus==='error'" class="error">{{errorMessage}}</p>
    </div>
</template>

<script>
//绑定label和prop属性
//获取当前输入框的规则
//如果输入框和ruler不匹配,显示错误信息
//input组件中,用户输入内容的时候,通知formItem的做校验(校验的方法)
//使用async-validate做校验

//npm i async-validator -S 安装
import Schema from 'async-validator';
export default {
    data() {
        return {
            validateStatus:"",//校验的状态值
            errorMessage:"", //显示的错误信息
        }
    },
    inject:["form"]
    ,
    props:{
        label:{
            type:String,
            default:""
        },
        prop:{ //这个prop指的是age或者pass
            type:String,
            default:""
        },
    },
    //🍊这里涉及一个生命周期的调用,子组件的内部方法先走完,走完之后再去走父组件的created方法
    created() {
        this.$on("validate",this.validate)
    },
    methods: {
        validate(value){
            //当前的value是输入框的值
          console.log("我是输入框输入的值",value);  
          console.log("我是provide的form实例上的规则rules",this.form.rules);
          console.log("我是prop",this.prop);
          //下面开始进入校验的逻辑了
            //此对象要存储校验规则这个校验规则(实际上是从Form组件中拿到的)
            //让descriptor变成动态的值
            // let descriptor = {};
            // descriptor[this.prop] = this.form.rules[this.prop];
          const descriptor ={[this.prop]:this.form.rules[this.prop]};
          const validator =  new Schema(descriptor);
            // let obj = {};
            // obj[this.prop] = value;
            const obj = {[this.prop]:value }

          validator.validate(obj,errors=>{
              if(errors){
                  //显示你的错误
                  this.validateStatus = "error";
                  this.errorMessage =  errors[0].message;

              }else{
                  //错误置空
                  this.validateStatus = "";
                  this.errorMessage = "";
              }
          })
        }
    },
}
</script>

<style scoped>
    .error{
        color: red;
    }
</style>

注意事项:

  • 项目目录下需要安装async-validator,命令行:npm i async-validator -S
  • FormItem需要拿到外层的FormComponent组件的rules,这个需要时候可以通过provideinject来传递一个FormComponent的实例给FormItem组件,从而拿到FormCompenent的规则rules

3.FormComponent组件:

//FormComponent.vue

<template>
    <div>
    <!--插槽--用来包裹的FormItem等-->
        <slot></slot>
    </div>
</template>
<script>

export default {
  //通过provide将自己的实例传递给内层的FormItem,这样不管中间间隔了div或者其他元素,都可以获得rules
    provide(){
        return{
            "form":this
        }
    },
    props:{
        model:{
            type:Object,
            required:true
        },
        rules:{
            type:Object
        }
    }
}
</script>
<style scoped>
    
</style>

4.三合一合成From组件:

//Form.vue

<template>
<div>   
<!--这是我们自己的input组件-->
    {{ruleForm}}
    <m-form :model="ruleForm" :rules="rules">
      <m-form-item label="用户名" prop="name">
        <m-input v-model="ruleForm.name"></m-input>
      </m-form-item>
      <m-form-item label="年龄" prop="age">
        <m-input type="age" v-model="ruleForm.age"></m-input>
      </m-form-item>
      <m-form-item lable="密码" prop="pass">
        <m-input type="password" v-model="ruleForm.pass"></m-input>
      </m-form-item>
    </m-form>
</div>

</template>

<script>
import MInput from "./Input";
import MFormItem from "./FormItem";
import MForm from "./FormComponent";
  export default {
    components:{
        MInput,
        MFormItem,
        MForm
    },
    data() {
       return {
           ruleForm: {
               pass: '98',
               age: "18",
               name: "索隆",
           				},
           rules: {
               name: [
                 {
                   required: true,
                   message: "请输入名字"
               		}, 
                 {
                   min: 5,
                   max: 10,
                   message: "请输入5~10位用户名"
               		}
               ],
               pass: [
                 {
                   require: true,
                   message: "请输入密码"
               		}, 
                 {
                   min: 6,
                   max: 10,
                   message: "请输入6~10密码"
               		}
               ],
               age: [
                 {
                   require: true,
                   message: "请输入年龄",
               		},
               ],
           }
       };
   },
    methods: {

    }
  }
</script>

项目中通过npm run erve 运行后,可以看到相关的校验规则起作用了。