Bootstrap

element表单校验

参考文章:element表单校验新玩法:一键定位未通过字段位置_修改 element form表单验证信息位置-CSDN博客
表单校验:当表单校验未通过时,能够直接定位到未通过字段位置,能够让用户快速找到错误的地方进行修改,方便用户操作提高用户的效率。


实现效果:

效果1:
在这里插入图片描述

效果2:
在这里插入图片描述

主要步骤:

1. 在必填校验的el-form-item元素中添加ref

ref 作用主要是用来定位(ref 的值建议与 prop 同名)

代码如下:

 <el-form ref="formRef" :model="state.form" class="formTable">
        <div class="FormLine h35">
          <div class="FormLabel">信息来源</div>
          <div class="FormContent">
            <el-form-item prop="shangbaolx" ref="shangbaolx" :rules="[{ required: true, message: '【信息来源】不能为空', trigger: 'change' }]">
              <el-select v-model="state.form.shangbaolx" size="large" placeholder="">
                <el-option v-for="item in informationSources" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </div>
          <div class="FormLabelSec">当事人</div>
          <div class="FormContent w105">
            <el-form-item prop="shijianzt" ref="shijianzt" :rules="[{ required: true, message: '【当事人】不能为空', trigger: 'blur' }]">
              <el-input v-model="state.form.shijianzt" type="text" />
            </el-form-item>
          </div>
          <div class="FormContentThird">
            <el-checkbox v-model="unknown" label="未知" size="large" />
          </div>
        </div>
        
        <div class="FormLine h70">
          <div class="FormLabel">事件描述</div>
          <div class="FormContentLong h70">
            <el-form-item prop="shiJianms" ref="shiJianms" :rules="[{ required: true, message: '【事件描述】不能为空', trigger: 'blur' }]">
              <el-input :rows="2" v-model="state.form.shiJianms" :cols="40" type="textarea" placeholder="请输入事件描述……" />
            </el-form-item>
          </div>
        </div>
        <div class="FormLine h70">
          <div class="FormLabel">事件备注</div>
          <div class="FormContentLong h70">
            <el-form-item prop="beizhu" ref="beizhu" :rules="[{ required: true, message: '【事件备注】不能为空', trigger: 'blur' }]">
              <el-input :rows="2" v-model="state.form.beizhu" :cols="40" type="textarea" placeholder="请输入事件备注……" />
            </el-form-item>
          </div>
        </div>
        </el-form>
      <div class="bottomArea">
        <el-button type="primary" @click="register" size="default">登记</el-button>
      </div>

提示:如果只想实现效果1,那么到此就可以结束了(效果1的实现只需添加rules规则,当鼠标点击失焦后显示红框和提示字):

2. 把提交校验的validate方法进行封装,在提交的时候先调用校验方法进行非空判断;

弹框显示未填写的字段
代码如下:

const register = async () => {
  formRef.value.validate(async (valid: boolean, object) => {
    if (valid) {
      //校验通过执行逻辑
    } else {
      nextTick(() => {
        let str = []
        for (let key in object) {
          object[key].map((item) => {
            str.push(item.message)
          })
          let dom = Object.keys(object)[0].valueOf
          if (Object.prototype.toString.call(dom) !== '[object Object]') {
            dom = dom[0]
            break //结束语句并跳出语句,进行下个语句执行
          }
          // 定位代码
          dom.$el.scrollIntoView({
            block: 'center',
            behavior: 'smooth',
          })
        }
        // 页面提示未通过校验字段项,并以逗号分隔
        ElMessage.error(str.join(','))
      })
    }
    if (!valid) {
      ElMessage.error({ message: '请检查将表格输入完整', grouping: true })
      return
    }
  })
}

3. 应甲方要求去除红框和下方提示

因为甲方爸爸觉得红色提示框太多太乱,决定以弹窗提示的方式进行,由于本人技术有限,没有什么好的方法,直接使用了原始的css样式进行样式隐藏(如果大佬们有更好的方法,欢迎来讨论TAT)

/*--------验证-不显示红框和提示--------*/
::v-deep .el-form-item.is-error .el-select__wrapper {
  box-shadow: 0 0 0 0px;
}
::v-deep .el-form-item.is-error .el-textarea__inner {
  box-shadow: 0 0 0 0px;
}
::v-deep .el-form-item.is-error .el-input__wrapper {
  box-shadow: 0 0 0 0px;
}
::v-deep .el-form-item__error {
  opacity: 0;//透明度(即提示字不显示)
}

总结

*总体思路:
1、给提交事件添加一个参数 object ;
2、当校验不通过时收集所有未通过字段项提示信息,将其通过 push 方法添加到定义好的数组中(str);
3、通过 Object.keys(object)[0].valueOf 获取到首个字段校验不通过的提示信息;
4、利用Object.prototype.toString.call() 方法判断 Object.keys(object)[0].valueOf 的类型是否为对象的字符串形式;
5、最后通过 scrollIntoView 方法滚动到首个不通过校验字段项。

!!温馨提示:如果在必填项里面使用了v-show或者v-if判断,一定一定要选择v-if来进行判断(使用v-show,即使元素被隐藏依旧会被dom捕获,从而提示该元素未填写)

;