Vue Router 数据获取
数据获取
有时候进入某个路由后,需要从服务器获取数据。
可从两种方式来实现:导航完成后获取、导航完成前获取。
导航完成后获取(先跳转,再渲染数据)
先完成导航,再在接下来的组件生命周期钩子(created)中获取数据。
数据获取期间,显示‘加载中’之类的提示。
注:最初始生命周期钩子created在全局后置钩子afterEach之后执行,也就是created()会在导航后执行。
思路:
设置一个元素来显示‘loading’提示,v-if属性为data变量,初始值为false,一开始并不显示。
在created钩子中调用获取数据的方法。
在methods中定义获取数据的方法:向服务器发送请求前显示‘loading’提示,向服务器请求数据,请求方法的回调函数中关闭'loading'提示,并且将获取到的数据渲染到页面上。
在watch中监视'$route'路由对象,当路由发生变化,则会再次执行获取数据的方法。
实现:
<template>
<div class="post">
<div v-if="loading" class="loading">
Loading...
</div>
<div v-if="error" class="error">
{{ error }}
</div>
<div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// 组件创建完后获取数据,
// 此时 data 已经被 observed 了
this.fetchData()
},
watch: {
// 如果路由有变化,会再次执行该方法
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
// replace getPost with your data fetching util / API wrapper
getPost(this.$route.params.id, (err, post) => {
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
导航完成前获取(先渲染数据,再跳转)
导航完成前,在路由进入的守卫(beforeRouteEnter)中获取数据,在数据获取成功后执行导航。
注:在守卫中获取并渲染数据,肯定得选能使用this的守卫,全局的肯定不能用,只能用组件内守卫,一般使用beforeRouteEnter就可以了。
思路:
在beforeRouteEnter守卫中,向服务器发送请求,请求方法的回调函数中调用next(),next()参数设置回调函数,渲染数据。
因为只改变动态段的话,依然进入同一个组件,复用的组件并不会进入beforeRouteEnter守卫,而是会进入beforeRouteUpdate,所以还要另外添加一个beforeRouteUpdate,同样向服务器获取数据。
实现:
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改变前,组件就已经渲染完了
// 逻辑稍稍不同
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
在为后面的视图获取数据时,由于是先渲染后导航(跳转),用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的提示。如果数据获取失败,同样有必要展示一些全局的错误提醒。