Nuxt3非组合式组件多useFetch调用异常求助
问题
我用非组合式(选项式API)编写Nuxt3组件,不想重构。为避免客户端与服务端重复请求,选择用useFetch而非$fetch。仅调用一次useFetch并通过.data.value取值时一切正常,但添加第二个useFetch调用后,出现错误:[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook,etc。
正常运行代码
export default { async serverPrefetch() { const store = useDataStore() await this.fetchData(store); }, mounted() { const store = useDataStore() this.fetchData(store); }, methods: { async fetchData(store) { const yesterdayBevData = await useFetch('/api/yesterdayBevs') store.setYesterdayBevs(yesterdayBevData.data.value) const bevData = await $fetch('/api/getBevSection/1') store.setBevModels(bevData) }, } }
异常代码(将一处$fetch替换为useFetch)
export default { async serverPrefetch() { const store = useDataStore() await this.fetchData(store); }, mounted() { const store = useDataStore() this.fetchData(store); }, methods: { async fetchData(store) { const yesterdayBevData = await useFetch('/api/yesterdayBevs') store.setYesterdayBevs(yesterdayBevData.data.value) const bevData = await useFetch('/api/getBevSection/1') store.setBevModels(bevData.data.value) }, } }
我尝试用runWithContext包裹每个useFetch调用,错误消失,但第二个请求在客户端出现了不必要的重复请求:
const nuxtApp = useNuxtApp() const bevData = await nuxtApp.runWithContext(() => useFetch('/api/getBevSection/'+key)) const yesterdayBevData = await nuxtApp.runWithContext(() => useFetch('/api/yesterdayBevs')) store.setYesterdayBevs(yesterdayBevData.data.value) store.setBevModels(bevData.data.value.bev)
请问如何实现在非组合式组件中发起多个请求,同时避免客户端重复请求?
解决方案
核心问题原因
- 选项式API的
methods不在Nuxt的组合式上下文范围内,直接在methods中调用多个useFetch会触发上下文缺失错误。 - 单独用
runWithContext包裹每个useFetch,会破坏Nuxt内置的请求缓存与服务端数据hydration机制,导致客户端无法复用服务端已获取的数据,从而重复请求。
正确实现方式
将数据获取逻辑放在setup函数中(处于Nuxt组合式上下文),再在serverPrefetch和mounted中调用该逻辑,同时在客户端判断数据是否已存在,避免重复请求:
export default { setup() { const store = useDataStore() // 定义在组合式上下文内的数据获取函数 const fetchData = async () => { // useFetch会自动处理服务端缓存与客户端hydration const yesterdayBevRes = await useFetch('/api/yesterdayBevs') store.setYesterdayBevs(yesterdayBevRes.data.value) const bevRes = await useFetch('/api/getBevSection/1') store.setBevModels(bevRes.data.value) } return { fetchData } }, // 服务端预获取数据 async serverPrefetch() { await this.fetchData() }, // 客户端仅在数据缺失时请求 async mounted() { const { yesterdayBevs, bevModels } = useDataStore() if (!yesterdayBevs || !bevModels) { await this.fetchData() } } }
关键说明
setup函数是Nuxt组合式上下文的入口,在此处调用useFetch能保证上下文正确,不会触发错误。useFetch内置了服务端数据序列化与客户端复用逻辑,只要在同一上下文内调用,客户端会自动复用服务端已获取的数据,无需额外处理。- 在
mounted中判断数据是否存在,避免服务端已预取数据后,客户端再次发起重复请求。
内容的提问来源于stack exchange,提问作者Michail Michailidis
相关产品推荐
相关产品推荐

