记录Nuxt.js中开发遇到的坑

最近在捣鼓线上博客,没尝试过ssr,于是使用nuxt.js来开发,接口使用的是koa。在nuxt开发时遇到了几个坑(注意事项)于是记录一下:

关于asyncData

asyncData根据官网和大部分文章的介绍,这个api是充当在服务端调用异步接口的作用。服务端通过asyncData调用数据之后返回数据,渲染完整个页面之后,返回给前端。这就导致了在asyncData中我们无法使用this来获取数据。因为this是前端的概念,而asyncData是在服务端。
为了请求数据我安装了@nuxtjs/axios并根据文档,在nuxt.config.js中进行配置:

modules: [
    '@nuxtjs/axios'
],
 axios: {
    proxy: true,
    withCredentials: true
  },

作为一个有经验的工程师,肯定要给axios做一些拦截器封装,在plugins/axios.js中:

export default function ({ store, redirect, req, router, app: { $axios } }) {
  $axios.defaults.baseURL = '/api'    // 为了代理

  $axios.onRequest((config) => {})

  $axios.interceptors.response.use(
    (response) => {
      return response.data
    },
    (error) => {
      return Promise.reject(error.response)
    })
}

然后在nuxt.config.js中进行配置:

plugins: [
    '@/plugins/axios'
],

本地接口没有设置跨域这个鬼东西,于是需要本地自己配置一波:

proxy: {
    '/api/': {
      target: 'http://localhost:8888',
      pathRewrite: {
        '^/api/': '/',
        changeOrigin: true
      }
    }
},

好了在页面的mounted方法中调用,成功:

mounted () {
    this.initData()
  },
  methods: {
    async initData () {
      // 之前有给axios设置baseURL = '/api',所以代理成功了
      const res = await this.$axios.get(`/article?page=1`)
      this.list= res.data
      this.total= res.count
    }
  }

然而我试图在asyncData这么操作时失败了:

async asyncData ({ app, params }) {
    const res = await app.$axios.$get('/article?page=1')
    return {
      list: res.data,
      total: res.count,
      page: 2
    }
  },

在这里插入图片描述
renderContext.renderResourceHints is not a function,emmm我觉得我的操作没问题,也找了好久,没发现什么BUG,于是去找了@nuxtjs/axios官网,发现人家在asyncData中请求地址是带了域名的,于是:

async asyncData ({ app, params }) {
    const res = await app.$axios.$get('http://localhost:8888/article?page=1')
    return {
      list: res.data,
      total: res.count,
      page: 2
    }
  },

在这里插入图片描述
结果木有任何问题Orz…本真大胆推测小心求证我做了下面几件事:

  1. 先确保后端接口没有设置Access-Control-Allow-Origin
  2. 删除axios.baseUrl的设置;
  3. 设置配置文件中关于代理的配置,在asyncData请求带域名时,可以请求成功,但是在mounted中请求带域名时却报了跨域问题
    在这里插入图片描述
  4. 设置axios.baseUrl = ‘api’;
  5. 设置代理;
  6. mounted中使用不带域名的请求,请求成功。
    所以我总结出了一个不知道对不对的道理:axios的配置是针对前端的,所以在mountedbaseUrl和代理是有效的;而asyncData是针对服务端的,所以baseUrl和代理没有作用,且请求的时候需要使用完整的接口路径。

页面跳转和参数获取

由于详情页面的渲染也要借助asyncData,所以获得页面路由id时发现asyncData只能通过params参数获取,所以创建详情文件的时候,需要使用这样的目录:
在这里插入图片描述
点击列表项跳转时,需要使用:

handleClick () {
      this.$router.push({
        path: `/details/${this.item.id}`
      })
}

所以在详情页获取接口数据时是这么写的:

async asyncData ({ params, app }) {
    const res = await app.$axios.$get(`http://localhost:8888/article/details?id=${params.id}`)
    return {
      info: res
    }
  },

列表分页

首页的列表本来是做了点击按钮之后切换上下页面的,然而发现假设在第二列表页面,点击进入详情,然后返回时,又会重新触发首页的asyncData,所以数据是第一页的数据。苍天的…
在这里插入图片描述

于是只能改称页面触底之后自动加载第二页,还会nuxt.js还有点人性啊,返回来之后会自动记录上次离开的位置,所以有位置并不一定准…
在这里插入图片描述

点击跳转数据可以正常加载,刷新却出现了问题

这是个大坑啊,前面我们提到了,我的后台接口没有设置跨域,在使用asyncData我使用了全程接口
首页页(列表页):

async asyncData ({ app }) {
    const res = await app.$axios.$get('http://localhost:8888/article?page=1')
    return {
      list: res.data,
      total: res.count
    }
  },

详情页:

 async asyncData ({ params, app }) {
    const res = await app.$axios.$get(`http://localhost:8888/article/details?id=${params.id}`)
    return {
      info: res
    }
  },

从首页点击跳到详情页,竟然发生了这种惨状…
在这里插入图片描述
刷新,我的详情页又回来了:
在这里插入图片描述
返回到首页:
在这里插入图片描述
TAT,我哭了,那么我修改一下详情页的请求,不携带域名:(这里我开了代理)

async asyncData ({ params, app }) {
    const res = await app.$axios.$get(`/article/details?id=${params.id}`)
    return {
      info: res
    }
  },

然后首页跳转到详情没有问题,详情返回出首页依旧数据有问题,如果直接在详情刷新还会给一个BUG提示语…到这里我的心态已经崩了。
最后我找到了一个一劳永逸的办法,默默在我的koa接口项目设置了跨域:

app.use(async (ctx, next) => {
  ctx.set("Access-Control-Allow-Origin", "*")
  await next()
})

首页和详情页都使用带有域名的接口地址,完事~
在这里插入图片描述
即,让后端设置一下跨域,前端直接使用完整的接口路由,不要借助代理了Orz,好了我明天去尝试一下部署到服务器上会不会有问题…

未完待续…


如有错误的地方,欢迎指出,谢谢~

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值