使用vue-query和invalidateQueries()避免保存后立即重新加载
解决Vue Query中更新缓存无需重新请求的问题
你现在的问题在于用invalidateQueries会触发缓存失效后的自动重新请求,但既然mutation成功后已经从服务器拿到了最新的记录,完全可以直接更新缓存内容,而非让缓存失效再重新拉取。
具体解决步骤
核心是使用queryClient.setQueryData方法,直接将mutation返回的最新数据写入对应缓存,替代invalidateQueries:
- 修改mutation的
onSuccess回调
把原来触发缓存失效的代码,换成直接更新指定queryKey的缓存:
onSuccess: (updatedRecord) => { // 直接更新当前项目的缓存 queryClient.setQueryData(['projects', route.params.id], updatedRecord) // 可选:如果有列表页的projects缓存(queryKey为['projects']),可以同步更新单条数据 // queryClient.setQueryData(['projects'], (oldData) => { // return oldData?.map(item => item.id === updatedRecord.id ? updatedRecord : item) // }) }
- 优化组件数据依赖(可选但推荐)
你现在单独维护了recordref,其实可以直接使用useQuery返回的data,缓存更新后组件会自动响应,不用手动赋值:
// 去掉单独的record ref // let record = ref({}) // 修改useQuery的queryFn,直接返回数据 const { isLoading, isFetching, isError, data, error, refetch } = useQuery({ queryKey: ['projects', route.params.id], queryFn: () => api.get(route.params.id), }) // 模板里直接用data.value <input name="name" :value="data?.name" :id="data?.id">
修改后的完整代码示例
<script setup> import { useDataLoader } from '../lib/dataLoader.js' import { watch } from 'vue' import { useRoute } from 'vue-router' import { useQuery, useQueryClient, useMutation } from "@tanstack/vue-query"; const route = useRoute() const api = useDataLoader('projects', { baseUrl: '/stores/1.0.0'}) const { isLoading, isFetching, isError, data, error, refetch } = useQuery({ queryKey: ['projects', route.params.id], queryFn: () => api.get(route.params.id), }) watch(() => route.params.id, () => { refetch() }) const queryClient = useQueryClient() const mutation = useMutation({ mutationFn: (formData) => api.put(route.params.id, formData), onSuccess: (updatedRecord) => { // 更新当前项目的缓存,避免重新请求 queryClient.setQueryData(['projects', route.params.id], updatedRecord) // 可选:同步更新projects列表缓存,取消下面注释 // queryClient.setQueryData(['projects'], (oldList) => { // return oldList?.map(item => item.id === updatedRecord.id ? updatedRecord : item) ?? [] // }) }, }) function save (e) { const formData = Object.fromEntries(new FormData(e.target)) mutation.mutate(formData) } </script> <template> <h1>Edit Project</h1> <form @submit.prevent="save"> <input name="name" :value="data?.name" :id="data?.id"> <input type="submit" value="Save"> </form> </template> <style> </style>
原理说明
invalidateQueries的作用是标记缓存为"失效",如果该缓存对应的查询正在被组件使用,Vue Query会自动触发重新请求来获取最新数据。- 而
setQueryData是直接修改缓存中的数据,既保证了缓存的新鲜度,又不会触发额外的网络请求,完全适配你这种"服务器已返回最新数据"的场景。
内容的提问来源于stack exchange,提问作者Merc
相关产品推荐
相关产品推荐

