将 Axios 与 Vuex 结合使用
现在您已经了解了使用 Axios 的基础知识,是时候考虑如何将它与 Vuex 一起使用了。 一种简单的方法是使用 Vuex 处理对 API 的包装调用,使用 Axios 执行 HTTP 调用。
练习 10.02:在 Vuex 中使用 Axios
我们将采用之前的功能(加载影片(films)和船舶(ships)数组)并在 Vuex 存储的上下文中重建它。和以前一样,您需要使用 CLI 来构建新应用程序,并确保您要求包含 Vuex。 CLI 完成后,您也可以使用 npm 命令添加 Axios。
此练习与我们在练习 10.01 使用 Axios 从 API 加载数据中构建的第一个应用程序非常相似,但有一些细微的差别。我们先看一下用户界面。初始加载时,Films 和 Ships 都是空的:

请注意,Films 部分有一条加载消息。应用程序加载后,我们将立即发出获取该数据的请求。 不过,对于 Ships,我们会等待用户明确请求他们想要该数据。这是 films 数组加载后的样子:

最后,单击 Load Ships 按钮后,该按钮将禁用(以防止用户多次请求数据),然后在数据加载后删除整个按钮:

要访问本练习的代码文件,请参阅 https://packt.live/32pUsWy 。
-
从第一个组件 App.vue 开始。 编写 HTML。 请记住,films 显示在组件中,但 ships 只将显示在其自己的组件中。 使用 v-else 添加一条加载消息,该消息将在 Axios 发出 HTTP 请求时显示:
<template> <div id="app"> <h2>Films</h2> <ul v-if="films.length"> <li v-for="film in films" :key="film.url"> {{ film.title }} was released in {{ film.release_date }} </li> </ul> <div v-else> <i>Loading data...</i> </div> <Ships /> </div> </template>
-
现在添加加载和注册 Ships 组件所需的代码:
import Ships from './components/Ships.vue' export default { name: 'app', components: { Ships },
-
也导入 mapState:
import { mapState } from 'vuex';
-
接下来,添加代码以将 films 数组从我们的存储映射到本地计算值。记得导入mapState:
computed: { ...mapState(["films"]) },
-
最后,created 方法用于在我们的 store 中触发一个操作:
created() { this.$store.dispatch('loadFilms'); }
-
接下来,在 Components/Ship.vue 中构建 Ships 组件。Ships 组件还包含一个数据列表,但使用一个按钮,以便用户可以请求加载数据。完成后该按钮应自动关闭,并在加载过程中禁用:
<template> <div> <h2>Ships</h2> <div v-if="ships.length"> <ul> <li v-for="ship in ships" :key="ship.url"> {{ ship.name }} is a {{ ship.starship_class }} </li> </ul> </div> <button v-else @click="loadShips" :disabled="loading">Load Ships</button> </div> </template>
-
添加代码来处理映射 ships 状态并触发 Vuex 的操作来加载 ships:
<script> import { mapState } from 'vuex'; export default { name: 'Ships', data() { return { loading:false } }, computed: { ...mapState(["ships"]) }, methods:{ loadShips() { this.loading = true; this.$store.dispatch('loadShips'); } } } </script>
-
现在,建立 store。首先,定义保存 films 和 ships 数组的状态:
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) export default new Vuex.Store({ state: { films:[], ships:[] },
-
接下来,添加加载船舶(ships)和影片(films)数据的操作。他们都应该使用突变(mutations)来为状态(state)分配值:
mutations: { setFilms(state, films) { state.films = films; }, setShips(state, ships) { state.ships = ships; } }, actions: { loadFilms(context) { axios.get('https://swapi.dev/api/films') .then(res => { context.commit('setFilms', res.data.results); }).catch(error => { console.error(error); }); }, loadShips(context) { axios.get('https://swapi.dev/api/starships') .then(res => { context.commit('setShips', res.data.results); }).catch(error => { console.error(error); }); } } })
-
使用以下命令运行您的应用程序:
npm run serve
您的输出将如下所示:

总而言之,与没有 Vuex 的初始版本相比,这并不是一个巨大的变化(如果我们忽略 UI 更改),但现在我们所有的 API 使用都由 store
处理。如果由于某种原因我们决定停止使用 Axios 并改用 Fetch
,可以在这里完成。无论我们决定添加缓存系统还是存储数据以供离线使用,都可以在 store
中完成。通过运行 npm run serve
并在浏览器中打开 URL 来自行测试此版本。
现在是时候将您所学到的知识运用到下一个活动中了!
活动 10.01:使用 Axios 和 Vuex 进行身份验证
使用 Vuex 可以做的更有趣的事情之一是管理身份验证。我们这么说是什么意思? 在许多 API 中,在使用服务之前需要进行身份验证。用户进行身份验证后,他们将获得一个令牌。 在将来调用 API 时,令牌通常作为标头传递,让远程服务知道这是授权用户。 Vuex 可以为您处理所有这些,而 Axios 可以轻松处理标头,因此让我们考虑一个实际的示例。
构建具有身份验证和授权的服务器远远超出了本书的范围,因此我们将伪造它。我们将有两个端点,它们是 JSONBin.io 的简单使用,这是我们在第 9 章使用 Vuex 中使用的服务 – 状态(State)、获取器(Getters)、操作(Actions)和突变(Mutations)。第一个端点url将返回一个 token 令牌:
{
"token": 123456789
}
第二个端点将返回猫(cats)数组:
[
{
"name": "Luna",
"gender": "female"
},
{
"name": "Pig",
"gender": "female"
},
{
"name": "Cracker",
"gender": "male"
},
{
"name": "Sammy",
"gender": "male"
},
{
"name": "Elise",
"gender": "female"
}
]
在本活动中,我们将使用 Vue Router 来处理表示应用程序的两个视图(views):登录屏幕和猫显示屏幕。
步骤:
-
显示应用程序初始视图的登录屏幕。它应该提示输入用户名和密码。
-
将登录凭据传递到端点并获取令牌。这部分将是伪造的,因为我们没有构建一个完整的、真实的身份验证系统。
-
从远程端点加载 cats 并将令牌作为身份验证标头传递。
您最初应该得到以下输出:

登录后,您将看到数据,如下:
