从 REST API 获取的 Vuex 渲染数据 [英] Vuex rendering data that is fetched from REST API
问题描述
对于这样的组件
<div><router-link :to={name:'section', params: { sectionId: firstSectionId }}">Start</router-link>
</模板><script lang="ts">从vuex"导入 { mapActions }导出默认{安装(){this.getSectionId()},计算:{firstSectionId() {返回 this.$store.state.firstSectionId}},方法:mapActions([getSectionId"])}
商店:
const store: any = new Vuex.Store({状态: {firstSectionId:空},//动作,//突变})
我在 getSectionId
操作中有一个 Web 请求,它异步获取数据并调用将在 state
中填充 firstSectionId
的突变.在初始渲染过程中 firstSectionId
是 null
并且我收到警告说在 router-link
渲染过程中缺少必需的参数.
这里添加v-if=firstSectionId"
不是问题.但一般来说,从服务器获取要显示的数据的方法是什么?目前我所有的组件都在渲染之前检查商店中是否存在数据,这是正常的还是有更好的方法来等待数据加载后再渲染?
异步获取数据的一种方法是在 vuex store actions 中使用 promise.
Vue.http.get(API_URL).then((响应) => {//使用响应对象}).catch((错误) => {console.log(error.statusText)});
为了证明我向这条路线提出请求.您可以看到响应应该是什么样子.让我们将响应对象保存在 state.users 数组中.
store.js
const store = new Vuex.Store({状态: {用户:[]},突变:{FETCH_USERS(状态,用户){state.users = 用户}},动作:{fetchUsers({ commit }, { self }) {Vue.http.get("https://jsonplaceholder.typicode.com/users").then((响应) => {提交(FETCH_USERS",response.body);self.filterUsers();}).catch((错误) => {console.log(error.statusText)});}}})导出默认存储
您注意到提交后有 self.filteruser()
方法.那是关键时刻.在此之前我们提交一个mutation,这是同步操作,我们确信我们将在store.state 中有我们的响应,可以在filterUsers()
方法中使用(不要忘记传递自我参数)
Users.vue
从../store/store"导入商店导出默认{名称:'用户',创建(){this.$store.dispatch("fetchUsers", { self: this })},方法:{过滤用户(){//对用户做一些事情console.log("用户--->",this.$store.state.users)}}}
更好的方法(ES6 和 ES7)
用于异步编程的 ES6 Promises
//User.vue创建(){this.$store.dispatch(fetchUser").then(() => {console.log(这将在调度后打印!!")})}//store.js动作:{fetchUser({ 提交 }) {返回新的承诺((解决,拒绝)=> {Vue.http.get("https://jsonplaceholder.typicode.com/users").then((响应) => {提交(FETCH_USERS",response.body);解决();}).catch((错误) => {console.log(error.statusText);});});}}
ES7:异步/等待
要摆脱回调地狱,并改进异步编程,请使用 async
函数,您可以 await
对 Promise 进行操作.代码看起来更容易理解(就像它是同步的),但代码对于浏览器来说是不可读的,所以你需要 Babel 转译器来运行它.
动作:{异步操作A({提交}){commit('gotData', 等待 getData())},异步操作B({调度,提交}){await dispatch('actionA')//等待 actionA 完成commit('gotOtherData', 等待 getOtherData())}}
For such component
<template>
<div>
<router-link :to="{name:'section', params: { sectionId: firstSectionId }}">Start</router-link>
</div>
</template>
<script lang="ts">
import { mapActions } from "vuex"
export default {
mounted() {
this.getSectionId()
},
computed: {
firstSectionId() {
return this.$store.state.firstSectionId
}
},
methods: mapActions(["getSectionId"])
}
</script>
Store:
const store: any = new Vuex.Store({
state: {
firstSectionId: null
},
// actions,
// mutations
})
I have a web request in the getSectionId
action and it asynchronously fetches data and calls a mutation that will fill firstSectionId
in state
. During the initial rendering firstSectionId
is null
and I get the warning that a required parameter is missing during rendering of router-link
.
It is not a problem here to add v-if="firstSectionId"
. But in general what is the approach for fetching data from a server to be displayed? Currently all my components are checking if there is data present in the store before rendering, is it normal or is there a better way to wait for data to be loaded before rendering it?
One approach for asynchronously fetching data is to use promise in vuex store actions.
Vue.http.get(API_URL)
.then((response) => {
//use response object
})
.catch((error) => {
console.log(error.statusText)
});
To demonstrate that I make request to this route. You can see how response should looks like. Let's save response object in state.users array.
store.js
const store = new Vuex.Store({
state: {
users: []
},
mutations: {
FETCH_USERS(state, users) {
state.users = users
}
},
actions: {
fetchUsers({ commit }, { self }) {
Vue.http.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
commit("FETCH_USERS", response.body);
self.filterUsers();
})
.catch((error) => {
console.log(error.statusText)
});
}
}
})
export default store
You noticed that there is self.filteruser()
method after commit. That is crucial moment. Before that we are committing a mutation, which is synchronous operation and we are sure that we will have our response in store.state that can be used in filterUsers()
method (don't forget to pass self parm)
Users.vue
import store from "../store/store"
export default {
name: 'users',
created() {
this.$store.dispatch("fetchUsers", { self: this })
},
methods:{
filterUsers() {
//do something with users
console.log("Users--->",this.$store.state.users)
}
}
}
Better ways (ES6 & ES7)
ES6 Promises for asynchronous programming
//User.vue
created() {
this.$store.dispatch("fetchUser").then(() => {
console.log("This would be printed after dispatch!!")
})
}
//store.js
actions: {
fetchUser({ commit }) {
return new Promise((resolve, reject) => {
Vue.http.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
commit("FETCH_USERS", response.body);
resolve();
})
.catch((error) => {
console.log(error.statusText);
});
});
}
}
ES7: async/await
To get away from callback hell, and to improve asynchronous programming use async
function, and you can await
on a promise. Code looks much easier to follow (like it is synchronous), but code isn't readable for browsers so you'll need Babel transpiler to run it.
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // wait for actionA to finish
commit('gotOtherData', await getOtherData())
}
}
这篇关于从 REST API 获取的 Vuex 渲染数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!