基于element-plus的二次开发的表单内容组件,可能会无法触发form表单校验,常见的情况为经过计算或者其他逻辑改变过modelValue的情况,比如
template
<template>
<el-input v-model="value" />
</template>
ts
<script setup lang="ts">
import { computed } from "vue";
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void;
}>();
const props = defineProps<{
modelValue?: string;
}>();
// 这是一种改变绑定值的情况
const value = computed({
get() {
// 这中间可能有其他格式化的方法或者处理逻辑,就不写了
return props.modelValue;
},
set(value: string) {
// 这中间可能有其他格式化的方法或者处理逻辑,就不写了
emits('update:modelValue', value);
}
});
// 还有一种是在方法里改变modelValue,比如输入框的change事件内
const handleInputValueChange = (value: string) => {
// 你可能需要处理一段复杂的逻辑,然后改变绑定值
emits('update:modelValue', value);
}
</script>
这只是最简单基于输入框二次封装的一个例子,可能有人说,他的能触发,这个我们不深究,因为确实有能触发的情况,但是我们做的项目可能定制程度比较高,中间逻辑有些复杂,就不能触发表单的校验规则了,不论规则配置的trigger值是change或者blur或者其他事件,都不能正常触发。
还有就是自定义的表单内容组件是肯定无法触发的。
要想做到跟element-plus自己的表单内容组件一样,你只需要引入element-plus内部的一个hook,叫useFormItem,上代码
import { useFormItem } from 'element-plus';
import { watch } from 'vue';
// form一般用不到,只是想告诉你它返回这两个值,一个是当前表单实例,一个是formItem实例
const { form, formItem } = useFormItem();
// 然后在你需要的时候调用formItem的validate方法
// 比如在modelValue改变的时候
watch(
() => props.modelValue,
() => {
// 几个注意点:
// 1、一定要用可选操作符,原因不赘述。
// 2、validate方法的参数是form rules内配置的trigger的值,比如我这里传入的是'change',它会在值改变的时候自动触发配置的trigger包含change的校验规则
formItem?.validate?.('change');
}
);
// 比如你想在输入框blur时候触发
const handleInputBlur = () => {
// 触发trigger包含blur的校验规则
formItem?.validate?.('blur');
}
上面的写法都来自于element-plus源码,可以放心写。useFormItem返回值的类型声明可以直接跳转element-plus类型声明查看,webstorm按住ctrl(mac为command)可以很方便跳转查看(Jetbrains打钱,再括弧(已购买三年全家桶,小伙伴们不要举报我,没用破解版))
第一次发帖,内容不精,多多包含。
对于自定义组件或者二开组件还有一种情况是可能需要用到表单上绑定的一些属性,比如form的size等内容,可以通过依赖注入的方式拿到,key是Symbol值,因为Symbol的特殊性,你必须从element-plus内引入这个值
// 这个路径可能不对,因为在某个版本之后这个文件的位置变了
// 这点要吐槽,element-plus内某些配置或者样式实现形式说改就改
import { formItemContextKey } from 'element-plus/es/tokens/form';
// 可以尝试,如果不好使就要再去找一下这个变量在源码中的位置了
import { formItemContextKey } from 'element-plus';