element-ui 2.x 版本中,如何在自定义组件上进行表单验证

通过查看element-ui Input组件的源码,我们可以看到它的校验规则如下

 watch: {
      value(val) {
        this.$nextTick(this.resizeTextarea);
        if (this.validateEvent) {
          this.dispatch('ElFormItem', 'el.form.change', [val]);
        }
      },
      ...
}

通过触发 this.dispatch('ElFormItem', 'el.form.change', [val]) 从而达到通知formItem组件的目的,那么我们自定义的组件也可以通过这种方式来实现校验


通过搜索dispatch方法,发现并不定义在文件中 ,通过引入的mixins可以推断出它的定义在element-ui/src/mixins/emitter.js中.

从而我们需要引入这个mixin,然后在组件中调用dispatch方法,就可以实现自定义组件的校验了



import emitter from 'element-ui/src/mixins/emitter';

export default {
  mixins: [emitter],

}

以上便完成了校验原理的分析,接下来我们来实现一个自定义组件的校验


实现一个自定义组件比如叫做my-input

script

import emitter from 'element-ui/src/mixins/emitter';
export default {
    mixins: [emitter],
    props: {
      value: {
        type: String,
        default: '',
      },
      validateEvent: {
        type: Boolean,
        default: true,
      },
    },
    watch: {
      value(val) {

        if (this.validateEvent) {
          this.dispatch('ElFormItem', 'el.form.change', [val]);
        }
      },
    },
}


template

<input :value="value" @input="e=>$emit('input',e.target.value)"/>

使用自定义组件

import myInput from './my-input.vue';
export default {
  components: {
    myInput,
  },
  data() {
    return {
      form: {
        name: '',
        age: '',
      },
      rules: {
        name: [
          { required: true, message: '请输入姓名', trigger: 'change' },
        ],
        age: [
          { required: true, message: '请输入年龄', trigger: 'change' },
        ],
      },
    };
  },
  methods: {
    submit() {
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.$message({
            message: '提交成功',
            type: 'success',
          });
        } else {
          this.$message({
            message: '提交失败',
            type: 'error',
          });
          return false;
        }
      });
    },
  },
};
<template>
  <div>
    <el-form ref="form" :model="form" :rules="rules" label-width="80px">
      <el-form-item label="姓名" prop="name">
        <my-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <my-input v-model="form.age" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submit">提交</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>