You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

关键修改点

  1. 从useForm中解构出setValues方法,用于手动更新表单值
  2. 使用Vue的watch监听props.initialData的变化,数据更新时调用setValues同步到表单
  3. 因initialData包含嵌套对象metadata,需开启deep: true深度监听

修改后,父组件的data更新(API返回最新数据)时,表单会自动同步显示最新值,无需刷新页面。

内容的提问来源于stack exchange,提问作者Rasik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:44:53