Nuxt 路由切换后 asyncData 跨域报错
背景
根据Nuxt 官方文档的说明
asyncData
方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。 但这个方法并不是每次都从服务端渲染,只有当页面刷新时才从服务端渲染,而在客户端点击链接跳转时并不从服务端渲染,而是和标准 Vue 单页面应用一样,从客户端进行渲染。
注意:
- 只能在页面组件中使用
asyncData
,也就是 pages 文件夹下的 .vue 文件中可以使用,非页面组件无法调用asyncData
方法- 没有
this
,因为asyncData
是组件初始化之前被调用的,所以在方法内是没有办法通过this
来引用组件的实例对象
所以这就是为什么每次我们点击路由跳转时,如果我们的目标页面有 asyncData
获取异步数据的时候,就会在浏览器端报跨域错误
// pages/index.vue
async asyncData({$axios}) {
const {result} = await $axios.get('http://localhost:3333/home/userinfo')
return {
userInfo: result.user_info
}
},
npm run dev
启动项目运行在 http://localhost:3000
本地启动一个 node 服务提供接口,服务运行在 http://localhost:3333
点击路由跳转会出现跨域报错如下:
刷新一下错误就没了,而且也能正常获取异步数据了。
解决跨域方案
npm i @nuxtjs/axios @nuxtjs/proxy
// plugins/request.js
// 用来统一返回接口的数据
export default function({app: {$axios}}) {
$axios.onResponse(response => {
return response.data
})
}
// nuxt.config.js
plugins: [
'@/plugins/request'
],
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true,
credential: true
},
proxy: {
'/api/': {
target: 'http://localhost:3333/',
pathRewrite: {
'^/api/': '/',
changeOrigin: true
}
}
},
// pages/index.vue
async asyncData({$axios}) {
const {result} = await $axios.get('/home/userinfo')
return {
userInfo: result.user_info
}
},
修改了 nuxt.config.js
内容记得重启
如何在组件中使用异步数据
如果组件不是和路由绑定的页面组件,原则上是不可以使用异步数据的。因为 Nuxt.js 仅仅扩展增强了页面组件的
data
方法,使得其可以支持异步数据处理。
对于非页面组件,有两种方式可以实现数据的异步获取:
- 在组件的
mounted
方法里面实现异步获取数据的逻辑,之后设置组件的数据,限制是:不支持服务端渲染。- 在页面组件的
asyncData
或fetch
方法中进行 API 调用,并将数据作为props
传递给子组件。服务器渲染工作正常。缺点:asyncData
或页面提取可能不太可读,因为它正在加载其他组件的数据。总之,使用哪种方法取决于你的应用是否需要支持子组件的服务端渲染。