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));
      }
    }
}


複製代碼
相關文章
相關標籤/搜索