Vue3+VeeValidate表单更新后返回编辑页数据不刷新问题
问题:Vue3 + VeeValidate表单提交后返回编辑页仍显示旧值
使用Vue3结合VeeValidate开发的表单,提交更新成功后返回编辑页,API已返回正确的更新数据,但表单仍显示旧值,直至页面刷新。
子组件(表单组件)
<script setup lang="ts"> import { useRouter } from 'vue-router' import { toTypedSchema } from '@vee-validate/zod'; import { useForm } from 'vee-validate'; import type { ProductCollectionsRecord } from '@/types/pocketbase-types'; import { editProductCollectionSchema } from '@/types'; import { useUpdateCollection } from '@/queries/collections'; const router = useRouter() const props = defineProps<{ initialData: ProductCollectionsRecord; }>(); const formSchema = toTypedSchema(editProductCollectionSchema); // 问题所在:initialValues仅执行一次 const { handleSubmit, values, setErrors } = useForm({ validationSchema: formSchema, initialValues: { title: props.initialData.title || '', description: props.initialData.description || '', handle: props.initialData.handle || '', metadata: JSON.stringify(props.initialData.metadata ?? {}, null, 2), }, }); const { mutateAsync } = useUpdateCollection(props.initialData.id); const onSubmit = handleSubmit(async (values) => { const updatedPayload: ProductCollectionsRecord = { ...props.initialData, ...values, }; await mutateAsync(updatedPayload, { onSuccess: () => { router.push('/collections') }, onError: (error) => { setErrors(error.fieldErrors) } }) }); </script> <template> <form @submit="onSubmit"> <FormField v-slot="{ componentField }" name="title"> <FormItem> <FormLabel>Title</FormLabel> <FormControl> <Input v-bind="componentField" /> </FormControl> </FormItem> </FormField> <FormField v-slot="{ componentField }" name="metadata"> <FormItem> <FormLabel>Metadata</FormLabel> <FormControl> <Textarea v-bind="componentField" /> </FormControl> </FormItem> </FormField> <Button type="submit">Update</Button> </form> </template>
父组件(编辑页)
<script setup lang="ts"> // 获取集合数据 const { status, data, error } = useCollection(route.params.id as string); </script> <template> <CardContent> <div v-if="status === 'pending'"> Loading... </div> <div v-else-if="status === 'error'"> Error: {{ error?.message }} </div> <div v-else-if="data"> {{ data }} <EditCollectionForm :initial-data="data" /> </div> </CardContent> </template>
查询钩子
export const useUpdateCollection = (id: string) => { return useMutation<ProductCollectionsResponse, FetchError, ProductCollectionsRecord>({ mutationFn: async (payload: ProductCollectionsRecord) => await update(id, payload), onSuccess: () => { // 使查询失效以重新获取最新数据 queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() }); queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.detail(id) }); }, }); }; export const useCollection = (id: string) => { const { data, ...rest } = useQuery<ProductCollectionsRecord>({ queryKey: collectionsQueryKeys.detail(id), queryFn: async () => get(id), staleTime: 0, // 尝试设置该值以强制获取最新数据 }); return { data, ...rest }; };
当前情况
- 用户编辑并提交表单→API更新成功
- 用户导航至/collections→查询已失效
- 用户再次点击编辑→API返回正确的更新数据
- 问题:表单仍显示初始渲染的旧值
API返回的正确更新数据
{ "id": "6ruu2bg3yvv0yk2", "title": "best-sellers", "description": "{\"attribute_id\":\"abc12\"}", "handle": "best-sellers-1", "metadata": { "attribute_id": "1ee332ds22e", "id": 4 }, "updated": "2025-05-25 05:09:12.042Z" }
原因及解决方案
原因
VeeValidate的useForm初始化时,initialValues仅执行一次,后续props.initialData更新时,表单内部不会自动同步新值。即使父组件传递的initialData已是最新数据,表单仍保留第一次初始化时的旧值。
解决方案
监听props.initialData的变化,手动调用VeeValidate提供的setValues方法更新表单值:
修改后的表单组件代码
<script setup lang="ts"> import { useRouter, watch } from 'vue' import { toTypedSchema } from '@vee-validate/zod'; import { useForm } from 'vee-validate'; import type { ProductCollectionsRecord } from '@/types/pocketbase-types'; import { editProductCollectionSchema } from '@/types'; import { useUpdateCollection } from '@/queries/collections'; const router = useRouter() const props = defineProps<{ initialData: ProductCollectionsRecord; }>(); const formSchema = toTypedSchema(editProductCollectionSchema); // 解构出setValues方法 const { handleSubmit, values, setErrors, setValues } = useForm({ validationSchema: formSchema, initialValues: { title: props.initialData.title || '', description: props.initialData.description || '', handle: props.initialData.handle || '', metadata: JSON.stringify(props.initialData.metadata ?? {}, null, 2), }, }); // 监听initialData变化,同步更新表单值 watch(() => props.initialData, (newData) => { setValues({ title: newData.title || '', description: newData.description || '', handle: newData.handle || '', metadata: JSON.stringify(newData.metadata ?? {}, null, 2), }); }, { deep: true }); // 开启深度监听,适配嵌套对象类型的metadata const { mutateAsync } = useUpdateCollection(props.initialData.id); const onSubmit = handleSubmit(async (values) => { const updatedPayload: ProductCollectionsRecord = { ...props.initialData, ...values, }; await mutateAsync(updatedPayload, { onSuccess: () => { router.push('/collections') }, onError: (error) => { setErrors(error.fieldErrors) } }) }); </script>
关键修改点
- 从
useForm中解构出setValues方法,用于手动更新表单值 - 使用Vue的
watch监听props.initialData的变化,数据更新时调用setValues同步到表单 - 因
initialData包含嵌套对象metadata,需开启deep: true深度监听
修改后,父组件的data更新(API返回最新数据)时,表单会自动同步显示最新值,无需刷新页面。
内容的提问来源于stack exchange,提问作者Rasik
相关产品推荐
相关产品推荐

