ElementUI form表单动态校验实现

5,345 阅读1分钟

起因

最近在项目中遇到,当用户注册时,如果信息错误的话,需要根据后端返回的错误信息,显示在表单下面,在网上查找了很多解决方案,绝大多数动态校验,并不是真的动态校验,而是在已经确认几种错误信息的情况下,根据相应条件,显示对应的信息,这与我们的需求不同。

实现原理

官方文档Form表单中,有写到Form-Item存在一个error插槽,这是自定义表单校验信息的显示方式,参数为 { error },我们需要利用这个插槽显示我们定义好的变量信息。

实现代码

假设我们有一个表单form,需要校验输入的账号name,账号的规则为字母数字下划线,且长度在5-20位之间,同时需在服务端进行重名检测。

html代码

<el-form ref="form" :model="form.data" :rules="form.rules" label-width="150px">
  <el-form-item label="用户名" prop="name" ref="name">
    <el-input type="text" v-model="form.data.name"></el-input>
    <!-- Error插槽 -->
    <span class="el-form-item__error" slot="error">{{form.dynamicError.name}}</span>
  </el-form-item>
  <el-form-item label="状态">
    <label>{{form.data.status}}</label>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" v-loading="loading" @click="submitForm">提交</el-button>
  </el-form-item>
</el-form>

vue结构代码

data() {
  return {
    loading: false,
    form: {
      dynamicError: {
        name: ''
      },
      data: {
        name: '',
        status: ''
      },
      rules: {
        name: [
          { validator: (rule, value, callback) => {
            const validName = str => (/^[\da-zA-Z_]{5,20}$/).test(str)
            if (!value) {
              this.form.dynamicError.name = '请输入用户名'
            } else if (!validName(value)) {
              this.form.dynamicError.name = '格式错误,用户名由6-20位字母、数字、下划线组成'
            } else {
              this.form.dynamicError.name = ''
              // 需要手动移除is-error带来的错误信息边框
              this.$refs.name.$el.classList.remove('is-error')
            }
            callback(this.form.dynamicError.name)
          }, trigger: 'change' }
        ]
      }
    }
  };
},
methods: {
  submitForm() {
    this.loading = true
    this.form.data.status = '提交中,请稍后'
    this.$refs.form.validate((valid) => {
      if (valid) {
        setTimeout(() => {
          this.loading = false
          if (Math.random() > 0.5) {
            this.form.data.status = '校验成功! 提交成功'
          } else {
            this.form.data.status = '校验成功,但未通过'
            this.form.dynamicError.name = '用户名已存在!'
            this.$refs.name.$el.classList.add('is-error')
          }
        }, 1000)
      } else {
        this.loading = false
        this.form.data.status = '校验未通过'
      }
    });
  }
}

在线测试地址