闽公网安备 35020302035485号

import {...,onMounted } from 'vue'
...
onMounted(()=>{
setTimeout(()=>{
dynamicValidateForm.email = '1372978934@qq.com'
},200)
})
...
问题分析const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
我们找到源码的form文件夹下的form.vue文件,并找到对应的resetFields方法定义,可以看到它执行了一个方法名称为resetField的函数const resetFields: FormContext['resetFields'] = (properties = []) => {
if (!props.model) {
debugWarn(COMPONENT_NAME, 'model is required for resetFields to work.')
return
}
filterFields(fields, properties).forEach((field) => field.resetField())
}
我们按照引用路径,找到form-item.vue文件,并找到resetField方法定义。可以看出,它从form表单上下文对象上根据表单上设置的prop找到对应的属性,getProp拿到的应当是当前的最新的表单项的值,接着它直接使用initialValue对该computedValue进行了覆盖。const resetField: FormItemContext['resetField'] = async () => {
const model = formContext?.model
if (!model || !props.prop) return
const computedValue = getProp(model, props.prop)
// 堆代码 duidaima.com
// prevent validation from being triggered
isResettingField = true
computedValue.value = clone(initialValue)
await nextTick()
clearValidate()
isResettingField = false
}
所以问题的关键就是initialValue是什么?initialValue是当前文件下的一个全局变量,并且它在onMounted中被设置了初始值let initialValue: any = undefined
onMounted(() => {
if (props.prop) {
formContext?.addField(context)
initialValue = clone(fieldValue.value)
}
})
看到这里我想你应该就明白了,由于form表单是作为业务组件的子组件,因此它会比业务组件早patched,这就意味着,这里的onMounted会先被执行,我们后续设置的值对element的form来说并不作为初始值被认可,因此,我好像冤枉人家element-plus了,根本原因好像是我们自己写的代码有问题。onBeforeMount(()=>{
dynamicValidateForm.email = '1372978934@qq.com'
})
可是,我这是需要从后台拉取的数据,是异步的,我怎么保证它比业务组件快呢?可能有些人会说了,你async一下不就完了嘛onBeforeMount(async ()=>{
dynamicValidateForm.email = await fetchValue()
})
const fetchValue = async ()=>{
return new Promise((resolve)=>{
resolve('1372978934@qq.com')
})
}
人家vue凭什么要为你埋单呢???所以啊,我们还是需要把他当成一个bug来处理的!!!(ps:开发期间为了优先完成任务我的做法是自己在内部缓存一份初始值,然后手动的进行重新设置)。
npx patch-package element-plusvue独享
delete FormItem.mounted
const FormItemPatched = {
extends: FormItem,
mounted() {
if (props.prop) {
formContext?.addField(context)
initialValue = clone(fieldValue.value)
window.onstorage = (payload)=>{
initialValue = payload
}
}
},
}
如此一来,我们就可以在业务组件中通过localStorage.setItem来将初始值传递给form-item内部了localStorage.setItem('somekey',initialValue)
这个方案几乎是完美的,我们只需要在我们当前这一个页面调用Vue.component进行注册,它就既能解决我们当下的问题,又不会影响到element-plus后续的更新。