自定义组件触发element-ui 表单校验

2,207 阅读1分钟

自己封装的自定义组件,想结合 form表单校验, 可参照如下示例

封装了一个 wap-input 组件, 期望组件能适当的触发 父组件的 form 的 表单校验, 和 el-form-item 一样效果

<template>
  <div class="input-wrap-container">
    <div class='label'>
      <template  v-if="label">{{label}}</template>
      <slot name='label' v-else></slot>
    </div>
    <el-input v-model="val" 
        @input="onInput" 
        @change="onChange"
        @blur="onBlur"
     />
  </div>
</template>

<script>
  import emitter from 'element-ui/src/mixins/emitter'
  let { methods: { dispatch } } = emitter
  
  export default {
    name: 'input-wrap',
    props: {
      value: [String, null],
      label: String
    },
    data () {
      return {
        val: ''
      }
    },
    mounted () {
      this.val = this.value
    },
    methods: {
      onInput(val) {
        this.$emit('input', val)
      },
      onChange () {
        // el-form 组件中有对这个事件的监听
        dispatch.call(this, 'ElFormItem', 'el.form.change', this.val)
      },
      onBlur () {
        dispatch.call(this, 'ElFormItem', 'el.form.blur', this.val)
      }
    }
  }
</script>

<style lang='less'>
  .input-wrap-container {
    display: flex;
    align-items: center;
    
    .label {
      min-width: 60px;
      margin-right: 12px;
    }
  }
</style>

手动触发 el.form.blur 或者 el.form.change 即可

父组件使用 , wrap-input 已经注册为全局组件了

<template>
  <el-form ref="form" :model="form" :rules="rules">
    <el-form-item label="对比" prop="name">
      <el-input v-model="form.name"></el-input>
    </el-form-item>
    <el-form-item prop="age">
      <wrap-input label="年龄" v-model="form.age"></wrap-input>
    </el-form-item>

    <div><el-button @click="checkData">提交校验</el-button></div>
  </el-form>
</template>

<script>
export default {
  data () {
    return {
      form: {
        range3: [],
        name: '',
        age: ''
      },
      rules: {
        name: [
          {
            type: 'string',
            required: true,
            message: '请输入姓名',
            trigger: ["blur", "change"]
          }
        ],
        age: [
          {
            type: 'string',
            required: true,
            message: '请输入年龄',
            trigger: ["blur", "change"]
          }
        ]
      }
    }
  },
  methods: {
    checkData () {
      this.$refs['form'].validate((valid, f) => {
        console.log("valid 校验是否通过", valid)
        console.log(`不通过的字段`)
        console.log(f)
      })
    },
  }
}
</script>

image.png

从 element-ui 源码中得知, 父组件是监听了这2个事件的, 只要手动触发即可

为什么子组件能触发顶层组件的事件呢 ? 这就得看 dispatch 的实现了

dispatch 中 一直找 父组件,只要匹配到父组件的 nameElFormItem 字符串相同, 就直接触发 el.form.blur 事件

image.png