使用 Axios 获取异步数据

我们已经使用 Koa 创建了一个简单的 API,并暴露了一些公共路由以供访问其数据,例如 /api/users 和 /api/users/1。我们还将此 API 与 Nuxt 集成到一个单独的应用程序中,其中 Nuxt 充当中间件。你已经了解了 asyncData 方法的工作原理以及我们如何使用 Nuxt 上下文。现在,让我们通过在 asyncData 方法中使用 Axios 来请求 API 数据,将这三个部分整合在一起,完成最后一步。

安装和配置 Axios

Axios 是一个基于 Promise 的 Node.js 应用程序 HTTP 客户端。我们在上一节中已经使用 asyncData 方法处理了原始的 Promise。我们可以使用 Axios 进一步简化我们的代码并节省一些代码行,Axios 由异步 JavaScript 和 XML (AJAX) 提供支持,用于进行异步 HTTP 请求。让我们通过以下步骤开始:

  1. 通过 npm 安装 Axios:

    $ npm i axios

    在使用 Axios 发出 HTTP 请求时,我们应该始终使用完整的路径:

    axios.get('https://jsonplaceholder.typicode.com/posts')

    但是,在每个请求的路径中都包含 https://jsonplaceholder.typicode.com/ 可能会很重复。此外,这个基本 URL 可能会随时间变化。因此,我们应该对其进行抽象并简化请求:

    axios.get('/posts')
  2. 在 /plugins/ 目录下创建一个 Axios 实例:

    // plugins/axios-api.js
    import axios from 'axios'
    export default axios.create({
      baseURL: 'http://localhost:3000'
    })
  3. 在需要它的组件中导入这个插件:

    import axios from '~/plugins/axios-api'

完成安装和配置后,我们就可以在下一节中获取异步数据了。

使用 Axios 和 asyncData 获取数据

好的,让我们按照以下步骤创建需要渲染数据的页面:

  1. 创建用户索引页面以列出所有用户:

    // pages/users/index.vue
    <ul>
      <li v-for="user in users" :key="user.id">
        <nuxt-link :to="'users/' + user.id'">
          {{ user.name }}
        </nuxt-link>
      </li>
    </ul>
    <script>
    import axios from '~/plugins/axios-api'
    export default {
      async asyncData ({ error }) {
        try {
          let { data } = await axios.get('/api/users')
          return { users: data.data }
        } catch (e) {
          // 处理错误
        }
      }
    }
    </script>

    在此页面上,我们使用 Axios 的 get 方法调用 /api/users 的 API 端点,该端点将被转换为 localhost:3000/api/users,用户列表的输出如下:

    {"status":200,"data":[{"id":1,"name":"Alexandre"},{"id":2,"name":"Pooya"},{"id":3,"name":"Sébastien"}]}

    然后,我们使用 JavaScript 的解构赋值 { data } 来解包输出中的 data 键。在使用 async/await 语句时,将代码包装在 try/catch 块中是一个好的做法。接下来,我们需要请求单个用户的数据。

  2. 创建单个用户页面以渲染单个用户数据:

    // pages/users/_id.vue
    <h2>
      {{ user.name }}
    </h2>
    <script>
    import axios from '~/plugins/axios-api'
    export default {
      name: 'id',
      async asyncData ({ params, error }) {
        try {
          let { data } = await axios.get('/api/users/' + params.id)
          return { user: data.data }
        } catch (e) {
          // 处理错误
        }
      }
    }
    </script>

    在此页面上,我们再次使用 Axios 的 get 方法调用 /api/users/<id> 的 API 端点,该端点将被转换为 localhost:3000/api/users/<id>,以获取单个用户的数据:

    {"status":200,"data":{"id":1,"name":"Alexandre"}}

同样,我们使用 JavaScript 的解构赋值 { data } 来解包输出中的 data 键,并将 async/await 代码包装在 try/catch 块中。

在下一节中,我们希望实现与本节相同的结果,即获取用户列表和特定用户的数据。但是,我们将在一个页面上使用 watchQuery 属性来完成此操作,你已经在上一节中学习了该属性。

监听查询变化

在本节中,我们将创建一个页面来监听查询字符串的变化并获取单个用户的数据。为此,我们只需要一个 .vue 页面来列出所有用户并监听查询,如果查询发生任何变化,我们将从查询中获取 id,并在 asyncData 方法中使用 Axios 获取具有该 id 的用户。让我们开始吧:

  1. 在 /pages/ 目录下创建一个 users-query.vue 页面,并将以下模板添加到 <template> 块中:

    // pages/users-query.vue
    <ul>
      <li v-for="user in users" :key="user.id">
        <nuxt-link :to="'users-query?id=' + user.id">
          {{ user.name }}
        </nuxt-link>
      </li>
    </ul>
    <p>{{ user }}</p>

    在此模板中,我们使用 v-for 指令遍历 users 中的每个用户,并将每个用户的查询添加到 <nuxt-link> 组件中。单个用户的数据将在 <ul> 标签之后呈现 <p> 标签内。

  2. 将以下代码添加到 <script> 块中:

    // pages/users-query.vue
    import axios from '~/plugins/axios-api'
    export default {
      async asyncData ({ query, error }) {
        var user = null
        if (Object.keys(query).length > 0) {
          try {
            let { data } = await axios.get('/api/users/' + query.id)
            user = data.data
          } catch (e) {
            // 处理错误
          }
        }
        try {
          let { data } = await axios.get('/api/users')
          return {
            users: data.data,
            user: user
          }
        } catch (e) {
          // 处理错误
        }
      },
      watchQuery: true
    }

    这段代码与 /pages/users/index.vue 相同;我们只是向 asyncData 添加了一个 query 对象,并根据 query 中的信息获取用户数据。当然,我们添加了 watchQuery: true 或 watchQuery: ['id'] 来监听 query 的变化。因此,在浏览器中,当你单击列表中的用户(例如 users-query?id=1)时,该用户的数据将呈现在 <p> 标签内,如下所示:

    { "id": 1, "name": "Alexandre" }

做得好!你已经完成了本章的学习。我们希望这对你来说是一个简单易懂的章节。除了使用 Axios 向 API 后端发出 HTTP 请求之外,我们还可以使用以下 Nuxt 模块之一:Axios 和 HTTP。本书重点介绍原始 Axios 和 Axios 模块。你还记得我们在第六章 “编写插件和模块” 中介绍了 Axios 模块吗?我们将在接下来的章节中经常使用这个模块。现在,让我们总结一下你在本章中学到的内容。

你可以在我们的 GitHub 仓库的 /chapter-8/nuxt-universal/koanuxt/using-axios/axios-vanilla/ 目录下找到上面的代码。如果你想了解更多关于 Nuxt HTTP 模块的信息,请访问 https://http.nuxtjs.org/ 。