在真实的项目中,数据都是从服务器端获取的,Vuex 中同样也支持从远程获取数据,从前面的知识里了解到,Action 是接收数据并处理逻辑的地方。
一般情况下,action 会接收外部传入的参数,然后执行网络请求,但是你需要添加 async 关键字
我们先看看如何使用 fetch 库,我们有一个获取用户列表的 json api
https://www.fastmock.site/mock/a9b15cd4db90d4e03ed76cd3c76d9197/f6/users
这个 API 返回的数据类似
{
"data": {
"users": [
{
"name": "Richard Harris",
"email": "k.yyziq@sdewmv.net"
}
]
}
}
看一下如何完成这个取数和渲染
Store
我们继续按照顺序来完成 store 的编写
state
根据上面的返回数据,我们可以设计好 state
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
users: []
}
});
mutation
我们需要定一个 load mutation函数用于更新 users
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
users: []
},
mutations: {
load(state, payload) {
state.users = payload;
}
}
});
action
由于网络请求是一个异步行为,所以在我们调用的时候,得借助 await/async ,action 的函数声明上就得添加 async 关键字,执行 request 语句也需要添加 await 关键字,代码如下:
axios
一般我们使用 axios 框架这个框架来做网络请求,当然你也可以选择使用 fetch,用法是一样的加上 await 关键字
没有用过 axios 框架的,可以看下它的 github 网址 https://github.com/axios/axios
这里使用 get 请求就可以得到数据啦,注意一下上面api的返回模型
import axios from "axios";
const response = await axios.get(
"https://www.fastmock.site/mock/a9b15cd4db90d4e03ed76cd3c76d9197/f6/users"
);
console.log(response.data);
axios 请求完后得到的是一个 http response 对象,所以如果想要获取服务器的内容,就需要读取这个 response 对象的 data 属性.
再对比一下 api 的返回数据
{
"data": {
"users": [
{
"name": "Richard Harris",
"email": "k.yyziq@sdewmv.net"
}
]
}
}
所以如果要想要获取 users api 的 users 返回值,你得console.log(response.data.data.users);
action 中运用 axios
完整的代码如下:
import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
users: []
},
actions: {
load: async ({ commit }) => {
const response = await axios.get(
"https://www.fastmock.site/mock/a9b15cd4db90d4e03ed76cd3c76d9197/f6/users"
);
commit("load", response.data.data.users);
}
},
mutations: {
load(state, payload) {
state.users = payload;
}
}
});
运用
最后在 User.vue 文件中添加 store 的依赖和配置
<template>
<div>
<ul v-for="user in users" :key="user.name">
<li>
<p>
<label>用户名</label>:
<span>{{user.name}}</span>
</p>
<p>
<label>邮箱</label>:
<span>{{user.email}}</span>
</p>
</li>
</ul>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
export default {
async mounted() {
await this.load();
},
computed: {
...mapState({
users: state => state.users
})
},
methods: { ...mapActions(["load"]) }
};
</script>