Vue-elementUI-From组件实现谁校验?


效果图以下:javascript


一、先建立一个input并添加$emit

//input.vue <template> <!-- v-bind="$attrs" 的做用是直接使用父级传过来的属性 --> <input :type="type" @input="onInput" :value="value" v-bind="$attrs" /> </template> <script> export default { inheritAttrs: false, props: { type: { type: String, default: "text" }, value: { type: String, default: "" } }, methods: { onInput(e) { this.$emit("input", e.target.value); //通知校验 this.$parent.$emit("validate"); } } }; </script>复制代码

二、FromItem校验

2.1获取input中$emit

//FromItem.vue <div class="from-item"> <label class="label" v-if="label">{{label}}</label> <slot></slot> <!-- 须要input触发校验 --> <div class="error" v-if="error">{{error}}</div> </div> </template> <script> import Schema from "async-validator"; export default { inject: ["form"], componentName: "k-form-item", props: { label: { type: String, default: "" }, prop: { type: String } }, data() { return { error: "" }; }, mounted() { //对应input中$emit this.$on("validate", () => { this.validate(); }); }, methods: { validate() { //执行校验 ); } } }; </script> <style scoped> .from-item { margin: 10px; display: flex; justify-content: center; } .label { padding-right: 10px; min-width: 90px; text-align: right; } .label::after { content: ":"; } .error { padding-left: 20px; color: #f00; } </style>复制代码

2.2 经过From的provide获取校验规则

//From.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>
<script>
export default {
  provide() {
    return {
      form: this
    };
  },
  props: {
    model: {
      type: Object,
      required: true
    },
    rules: {
      type: Object
    }
  },
};
</script>
复制代码

2.3 组件拼接index.vue

//index.vue

<template>
  <div> <KForm :model="model" :rules="rules" ref="loginForm"> <KFromItem label="用户名" prop="username"> <!--子集可经过 v-bind="$attrs" 获取placeholder="请输入用户名" 此类信息 --> <k-input v-model="model.username" placeholder="请输入用户名"></k-input> </KFromItem> <KFromItem label="密码" prop="password"> <k-input v-model="model.password" type="password" placeholder="请输入密码"></k-input> </KFromItem> <KFromItem> <button @click="onLogin">登陆</button> </KFromItem> </KForm> {{model}} </div> </template> <script> import KInput from "./KInput.vue"; import KFromItem from "./KFromItem"; import KForm from "./KForm"; export default { data() { return { model: { username: "wxy", password: "" }, rules: { username: { required: true, message: "必填项" }, password: { required: true, message: "必填项" } } }; }, components: { KInput, KFromItem, KForm, Notice }, }; </script> 复制代码

2.4 FromItem获取校验使用import Schema from "async-validator"校验

//FromItem.vue

methods: {
    validate() {
      //获取校验规则和当前值
      //此处使用form须要inject到form
      //this.prop须要提早声明
      const rules = this.form.rules[this.prop];
      const value = this.form.model[this.prop];

      //建立Schema实例
      const schema = new Schema({
        [this.prop]: rules
      });

      //使用该实例执行校验
      return schema.validate(
        {
          [this.prop]: value
        },
        errors => {
          if (errors) {
            this.error = errors[0].message;
          } else {
            this.error = "";
          }
        }
      );
    }
  }

复制代码

三、外部调用添加From总体校验

3.1 添加From总体校验

//From.vue 
methods: {
    validate(cb) {
      // 调用全部formitem的validate,只要一个失败就失败
      // 结果是Promise数组
      const task = this.$children
        .filter(item => !!item.prop)
        .map(item => item.validate());
      console.log("TCL: validate -> task", task);

      // 判断全部结果
      Promise.all(task)
        .then(() => cb(true))
        .catch(() => cb(false));
    }
  }

复制代码

3.2 调用From中的校验

//index.vue

<KFromItem>
        <button @click="onLogin">登陆</button>
</KFromItem>

 methods: {
    onLogin() {
      this.$refs.loginForm.validate(isValid => {
        console.log("TCL: onLogin -> isValid", isValid);
        if (isValid) {
          alert("请求登陆");
        } else {
          alert("登陆失败");
        }
      });
    }
  }
复制代码

四、优化input派发事件

优化KFromItem内不是input的状况css

<KFromItem label="密码" prop="password">
	<div>
      		  <k-input v-model="model.password" type="password" placeholder="请输入密码"></k-input>
	<div>
</KFromItem>


复制代码

methods: {
    onInput(e) {
      this.$emit("input", e.target.value);
      //this.$parent.$emit("validate");
      this.dispatch("k-form-item", "validate");
    },
 dispatch(componentName, eventName, params) {
      var parent = this.$parent || this.$root;
      var name = parent.$options.componentName;
      //若是父级存在        name存在或者name不等于传入的componentName都进入循环

      while (parent && (!name || name !== componentName)) {
        //新的父级元素
        parent = parent.$parent;
        if (parent) {
          //存在父级,就把新的父级的名字就从新赋值
          name = parent.$options.componentName;
        }
      }
      //结束循环条件 parent 不存在   &&  name不存在&&name==compontName
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    }
}


复制代码
相关文章
相关标签/搜索