NuxtJS中fetch钩子仅在导航时触发,刷新页面不执行问题
Nuxt页面刷新时fetch未触发请求的问题分析与解决
问题描述
刷新页面时,合约请求未在浏览器网络面板中出现;但通过NuxtLink跳转至其他页面后返回时,该请求会正常触发并显示在网络面板中,预期合约请求应在页面加载时执行。
相关代码
组件代码
<script> import { mapState } from 'vuex'; export default { layout: 'index', /** * Run State Dispatches */ async fetch({store}) { store.dispatch('api/contracts/all') }, /** * Create State Mapping */ computed: { ...mapState({ contracts: 'contracts' }) } } </script>
api/contracts模块代码
const axios = require("axios"); export const state = () => ({ contracts: [], }) export const mutations = { SET_CONTRACTS (state, contracts) { state.contracts = contracts } } export const actions = { async all({ commit }) { let response = await getApi(`/api/products`, this.$axios) let contracts = response.data commit('SET_CONTRACTS', contracts); } } const getApi = async function (url, axios) { let response = await axios.get(url) return { data: response.data } }
原因分析
SSR执行环境差异
刷新页面时Nuxt会触发服务端渲染(SSR),fetch方法在服务端运行,请求由服务端直接向后端发起,浏览器网络面板只能捕获浏览器自身发起的请求,因此看不到该请求。而通过NuxtLink跳转属于客户端导航,fetch在浏览器端执行,请求由浏览器发起,所以能在网络面板中看到。Vuex Action中axios调用错误
在服务端环境下,Vuex Action中的this并非Vue实例,调用this.$axios会直接抛出错误,导致请求无法正常执行。这也是刷新页面时请求未成功触发的核心原因之一,而客户端导航时this指向Vue实例,所以请求能正常执行。
解决方案
1. 修正Vuex Action的axios获取方式
从Action的上下文参数中解构$axios(Nuxt会自动将其注入到Vuex的context中),替换错误的this.$axios调用:
export const actions = { // 从context中解构$axios async all({ commit, $axios }) { // 使用解构得到的$axios,而非this.$axios let response = await getApi(`/api/products`, $axios) let contracts = response.data commit('SET_CONTRACTS', contracts); } }
2. 可选:强制fetch在客户端执行
如果希望刷新页面时也能在浏览器网络面板看到请求,可以给fetch方法添加server: false配置,强制其仅在客户端执行:
<script> import { mapState } from 'vuex'; export default { layout: 'index', // 强制fetch仅在客户端执行 fetch: { async handler({store}) { store.dispatch('api/contracts/all') }, server: false }, computed: { ...mapState({ contracts: 'contracts' }) } } </script>
额外提示
注意到Action中请求的是/api/products接口,但实际要获取的是合约数据,建议检查接口路径是否正确,改为/api/contracts避免数据错误。
内容的提问来源于stack exchange,提问作者Charlotte Wells
相关产品推荐
相关产品推荐

