【问题标题】:Writing client-side API libraries for Nuxt.js为 Nuxt.js 编写客户端 API 库
【发布时间】:2018-07-25 19:44:31
【问题描述】:

这更像是一个架构/设计问题,而不是“为什么这不起作用”。

我正在编写一个由外部 API (ExpressJS) 提供支持的 Nuxt.js SSR Web 应用程序。 API 负责身份验证(通过nuxt-auth - JWT)和检索用户数据等。据我了解,SSR 代码在客户端上设置了一个 cookie 并使用它来检索 JWT,以便通过 API 服务器进行身份验证,代表浏览器。

我已经为数据库中的每个模型编写了一些辅助方法,如下所示(简化):

// services/UserService.js
export default class UserService {
  constructor(ctx) {
    this.$axios = ctx.$axios
  }

  getUsers () {
    return this.$axios.get('/api/users')
  }

  createUser (params) {
    return this.$axios.post('/api/users', params)
  }

  updateUser (params) {
    return this.$axios.put('/api/users/' + params.id, params)
  }

  getUser (id) {
    return this.$axios.get('/api/users/' + id)
  }
}

这对 SSR 非常有效,因为我可以在我的 Nuxt 页面中做到这一点:

<template>{{user.display_name}}</template>

<script>
import UserService from '@/services/UserService'

export default {
  asyncData ({ params, $axios }) {
    const api = new ApiService({ $axios })

    return api.Users.getUser(params).then(user => {
      return { user, api } // this makes them available in the vue instance
    })
  }
}
</script>

现在,一旦它被渲染并发送到浏览器,下面可能会有一个响应式表单。当用户提交该表单以更新其个人资料时,我突然无法访问 UserService 实例。

这是因为它是在 asyncData 调用中定义的,只能在 SSR 上下文中使用。

我通过从 asyncData 方法返回 api 以及 user 来解决此问题,然后 Nuxt 将其放入 vue 实例。然而,这感觉非常错误。这是正确的方法吗?你应该怎么做?你不是吗?

这感觉特别糟糕,因为 Vue 会监视 data 中的所有内容,而我真的不需要它来跟踪 api 实例...

我对 Vue 和 Nuxt 还很陌生,所以如果我忽略了一些事情,请说,但我的问题是:

我应该如何设计它以在 SSR 上下文和浏览器中都工作?

谢谢!

【问题讨论】:

    标签: axios server-side-rendering nuxt.js


    【解决方案1】:

    我在这方面花了更多时间并想出了一个解决方案。

    我创建了一个插件来处理 api 对象的构造,然后将其添加到 Nuxt 上下文中,该上下文可供 SSR 代码和浏览器使用:

    // plugins/api.js
    
    import ApiService from '@/services/ApiService'
    
    export default (ctx, inject) => {
      const api = new ApiService({ $axios: ctx.app.$axios })
      ctx.$api = api
      inject('api', api)
    }
    

    // nuxt.config.js
    
    module.exports = {
      plugins: [
        '~/plugins/global.js',
        '~/plugins/datetimepicker.js',
        '~/plugins/axios.js',
        '~/plugins/api.js' // our plugin
      ],
      modules: [
        'bootstrap-vue/nuxt',
        '@nuxtjs/axios',
        '@nuxtjs/auth',
      ]
    }
    

    现在我的页面更加更干净了:

    <template></template>
    <script>
    export default {
      asyncData ({ params, $api }) {
        return $api.Users.getUser(params).then(user => {
          return { user }
        })
      }),
    
      watch {
        someValue (newVal) {
          // run in the browser
          this.$api.Users.doSomethingWith(val)
        }
      }
    }
    </script>
    

    我没有从中得到任何代码气味,但如果有 Nuxt 向导阅读此内容并发现了什么,请告诉我!

    【讨论】:

    • 用户类的最后一种形式是什么?我不清楚您如何将 axios 实例注入 Users 类?
    • @WebMan 我的 ApiService 构造函数将 axios 注入所有其他类并将它们设置为自身的属性。希望这是有道理的
    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 2020-03-02
    • 2021-04-11
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    相关资源
    最近更新 更多