Skip to content
文章目录

el-form问题相关

自定义表单项触发 el-form-item 的 rule 验证

适用于element-plus 2.x版本

ts
import { useFormItem } from 'element-plus'
import { nextTick } from 'vue'

/**
 * 用于自定义表单项组件触发el-form-item的校验事件 trigger。详见: https://juejin.cn/post/7041489184938262564
 */
export function useTrigger() {
  const { formItem } = useFormItem() // form formItem
  const emitTrigger = () => {
    if (formItem) {
      nextTick(() => {
        formItem.validate('blur') // 触发校验
        formItem.validate('change') // 触发校验
      })
    }
  }
  return { formItem, emitTrigger }
}

多语言切换后错误提示信息未一起更新

原因

element-plus 的错误提示信息,是在 rule 执行的时候,设置上去的,界面切换并不会使得 rule 执行,因此错误提示信息不会同步更新。

解决方式

错误提示信息不再传直接的错误提示,而传错误提示信息的 i18n 资源编码,再使用error slot将资源编码转为对应的语言文字

表单项错误提示信息未消失

常规检查点

  • el-form使用的model属性接收 form 值,而非v-model
  • el-formmodel属性名, 需要与el-form-itemprop对应
  • 自定义验证规则验证成功需要调用callback(), 并返回 true, 验证失败需要调用callback(new Error()), 并返回false

特殊情景说明

需求说明

之前在做动态表单,需要手动设置错误提示信息,因此对el-form-itemerror属性进行了手动设置,整体的实现方式为,先在最外层定义一个 errorInfo 对象,key为el-form-item的prop,value为{error:string,needDel:boolean}, 当errorInfo变化时,会自动去修改el-form-item的error属性

问题一:rule 验证失败,但界面没有错误提示信息

原因

errorInfo 的设置,将 rule 的设置覆盖了

描述

如果每次直接将errorInfo设置为一个新对象(如:errorInfo = newErrorInfo),那么会导致整个表单重新渲染,同时因为rule方式设置错误提示信息的顺序在手动设置el-form-item的error之前,那么会导致通过rule方式设置上去的验证信息,会被errorInfo的覆盖掉(表现形式就是:原本 rule 验证失败,应该设置一个错误提示信息上去,但由于一些情况errorInfo也被设置成了一个新对象,所以会在 rule 设置完错误提示信息之后,errorInfo 又设置一次,但由于 errorInfo 中没有 rule 中验证失败的 prop 的错误提示信息,所以,就设置成了 undefined,这样的话 errorInfo 就将 rule 的设置给覆盖了)

解决方式

不将errorInfo设置为新对象,而是每次去修改errorInfo的具体字段

该解决方式的原理

从 vue 的响应式更新和依赖收集分析,vue 的每个响应式数据,都会有自己的 Dept 或者说 Watcher, errorInfo的 Dept 就是整个el-form,因此你直接将errorInfo改成一个新对象,那不就得整个表单都更新,而errorInfo中的某个具体的属性,他们的Dept是某个具体el-form-item, 如果你只更新某个具体的属性,那么 vue 也只要更新某个具体的el-form-item,就不会影响到其他el-form-item

问题二:通过el-form-item的error属性设置的错误提示信息有时无效

原因

errorInfo的某个属性,多次设置相同的错误提示,并不会促使对应的el-form-item相关的 dom 重新渲染

描述

先执行 rule 的规则验证,如果 rule 验证失败,则会展示 rule 的错误提示信息,然后同样通过errorInfo手动设置rule验证失败的那个prop的错误提示信息,此时会显示errorInfo中的错误提示信息,在不修改表单数据的情况下,再执行 rule 的规则验证,因为表单数据未修改,所以 rule 的验证还是会失败,此时又会显示rule的错误提示信息,那么此时我再通过errorInfo手动设置rule验证失败的那个prop的错误提示信息,此时不会显示errorInfo中的错误提示信息,因为vue观察到errorInfo中的某个字段,第一次设置的值和第二次设置的值是一样的,因此会忽略这次操作,而我的期望是每次通过errorInfo设置错误提示信息时,界面都显示errorInfo中的

解决方式

在每次通过errorInfo设置某个prop的错误提示信息时,先delete errorInfo.某个prop, 促使 vue 重新渲染某个el-form-item, 然后在nextTick中再将 errorInfo.某个prop=错误提示信息, 设置上去,这样就能保证即使对errorInfo的某个prop属性设置同样的错误提示信息,vue 也一定会强制渲染对应的el-form-item

问题三:第一次 rule 验证通过,错误提示信息未消失

原因

未想清楚内部执行逻辑导致

描述

在 rule 中增加了一个验证规则,当 el-form-item 的旧值和新值不同时,将原本的错误提示信息标记为需要删除的(needDel=true),否则标记为不需要删除的(needDel=false)。同时因为更新动态表单中的errorInfo数据,是通过手动watch监听外部的errorInfo的变更实现的,那么此时rule中修改errorInfo中某个具体 prop 是否需要删除(needDel 从 false 变成了 true),同样造成了errorInfo的变化,被手动watch逻辑监听到了,但手动watch逻辑更新动态表单内部的errorInfo的某个prop时,未判断needDel是否为 false,因为只有为 false 的才需要重新设置,没判断的情况下,那就每次都设置了,所以会导致 rule 虽然验证通过,但第一次依然会有错误提示信息,但第二次却能去除错误提示信息,第二次为什么又能正常去掉错误提示信息呢?因为第二次errorInfo的某个prop的needDel属性是由true修改为true,所以不会触发手动watch逻辑,因此rule验证通过,就能清除界面的错误提示信息

解决方式

在更新动态表单内部的errorInfo之前,先判断当前这个触发更新的变更,needDel 属性值是 true 还是 false,如果是 true,则将动态表单内部 errorInfo 对象的对应 prop 删除,否则执行更新