如何让所有可见Vue组件重新获取Apollo查询?含缓存重置场景
实现方案
需求一:触发所有可见Vue组件重新获取Apollo查询
方案1:全局事件总线 + 组件内监听
这个方案适合需要手动触发(比如点击按钮)的场景,能精准控制哪些组件响应:
设置全局事件总线
- Vue3 可以用
mitt库或自定义简单事件发射器:// main.js import { createApp } from 'vue' import App from './App.vue' import mitt from 'mitt' const emitter = mitt() const app = createApp(App) app.config.globalProperties.$emitter = emitter app.mount('#app') - Vue2 直接用 Vue 实例本身作为总线:
// main.js import Vue from 'vue' import App from './App.vue' Vue.prototype.$bus = new Vue() new Vue({ render: h => h(App) }).$mount('#app')
- Vue3 可以用
组件内监听事件并触发refetch
- Vue3 Composition API:
import { useQuery } from '@vue/apollo-composable' import { gql } from 'graphql-tag' import { getCurrentInstance, onMounted, onUnmounted } from 'vue' export default { setup() { const instance = getCurrentInstance() const { refetch } = useQuery(gql` query FetchItems { items { id name } } `) const handleRefetch = () => refetch() onMounted(() => { instance?.proxy?.$emitter.on('refetch-all-apollo-queries', handleRefetch) }) onUnmounted(() => { instance?.proxy?.$emitter.off('refetch-all-apollo-queries', handleRefetch) }) return { /* 你的数据 */ } } } - Vue2 Options API:
import { gql } from 'graphql-tag' export default { apollo: { items: { query: gql`query FetchItems { items { id name } }` } }, mounted() { this.$bus.$on('refetch-all-apollo-queries', () => { this.$apollo.queries.items.refetch() }) }, beforeDestroy() { this.$bus.$off('refetch-all-apollo-queries') } }
- Vue3 Composition API:
触发全局事件
在需要触发的地方(比如某个按钮点击事件):// Vue3 this.$emitter.emit('refetch-all-apollo-queries') // Vue2 this.$bus.$emit('refetch-all-apollo-queries')
方案2:使用Apollo Client的resetStore()
如果你的目标是同时清除缓存并重新获取所有活跃查询,可以直接调用Apollo Client的resetStore()方法:
// Vue3 import { useApolloClient } from '@vue/apollo-composable' const { client } = useApolloClient() const refetchAllAndResetCache = async () => { await client.resetStore() } // Vue2 const refetchAllAndResetCache = async () => { await this.$apollo.client.resetStore() }
这个方法会自动清除InMemoryCache,并重新执行当前所有活跃的查询(可见组件中的查询都会重新获取数据)。
需求二:重置InMemoryCache后让组件自动响应
方案1:用resetStore()替代单独的cache.reset()
如上述方案,resetStore()会在清除缓存后自动重新执行所有活跃查询,组件无需额外代码就能获取最新数据。这是最省心的方式。
方案2:手动重置缓存后触发全局事件
如果你必须单独调用cache.reset()(比如不想重新执行所有查询,只针对部分组件),可以在重置缓存后触发之前设置的全局事件:
// Vue3 import { useApolloClient } from '@vue/apollo-composable' const { client } = useApolloClient() const resetCacheAndRefetch = async () => { await client.cache.reset() // 触发全局事件让组件重新获取 client.proxy?.$emitter.emit('refetch-all-apollo-queries') } // Vue2 const resetCacheAndRefetch = async () => { await this.$apollo.client.cache.reset() this.$bus.$emit('refetch-all-apollo-queries') }
方案3:设置查询的fetchPolicy
对于部分组件,你可以设置查询的fetchPolicy为cache-and-network,这样当缓存被重置后,组件会自动从网络获取最新数据(即使缓存为空):
// Vue3 const { result } = useQuery(gql`query FetchItems { items { id name } }`, null, { fetchPolicy: 'cache-and-network' }) // Vue2 apollo: { items: { query: gql`query FetchItems { items { id name } }`, fetchPolicy: 'cache-and-network' } }
这个方式适合不需要全局触发,只希望单个组件在缓存变化时自动响应的场景。
内容的提问来源于stack exchange,提问作者Vincent Cantin
相关产品推荐
相关产品推荐

