数据获取

有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:

  • 导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。

  • 导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

从技术角度讲,两种方式都不错 —— 就看你想要的用户体验是哪种。

导航完成后获取数据

当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

假设我们有一个 Post 组件,需要基于 $route.params.id 获取文章数据:

  1. <template>
  2. <div class="post">
  3. <div v-if="loading" class="loading">
  4. Loading...
  5. </div>
  6. <div v-if="error" class="error">
  7. {{ error }}
  8. </div>
  9. <div v-if="post" class="content">
  10. <h2>{{ post.title }}</h2>
  11. <p>{{ post.body }}</p>
  12. </div>
  13. </div>
  14. </template>
  1. export default {
  2. data () {
  3. return {
  4. loading: false,
  5. post: null,
  6. error: null
  7. }
  8. },
  9. created () {
  10. // 组件创建完后获取数据,
  11. // 此时 data 已经被 observed 了
  12. this.fetchData()
  13. },
  14. watch: {
  15. // 如果路由有变化,会再次执行该方法
  16. '$route': 'fetchData'
  17. },
  18. methods: {
  19. fetchData () {
  20. this.error = this.post = null
  21. this.loading = true
  22. // replace getPost with your data fetching util / API wrapper
  23. getPost(this.$route.params.id, (err, post) => {
  24. this.loading = false
  25. if (err) {
  26. this.error = err.toString()
  27. } else {
  28. this.post = post
  29. }
  30. })
  31. }
  32. }
  33. }

在导航完成前获取数据

通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。

  1. export default {
  2. data () {
  3. return {
  4. post: null,
  5. error: null
  6. }
  7. },
  8. beforeRouteEnter (to, from, next) {
  9. getPost(to.params.id, (err, post) => {
  10. next(vm => vm.setData(err, post))
  11. })
  12. },
  13. // 路由改变前,组件就已经渲染完了
  14. // 逻辑稍稍不同
  15. beforeRouteUpdate (to, from, next) {
  16. this.post = null
  17. getPost(to.params.id, (err, post) => {
  18. this.setData(err, post)
  19. next()
  20. })
  21. },
  22. methods: {
  23. setData (err, post) {
  24. if (err) {
  25. this.error = err.toString()
  26. } else {
  27. this.post = post
  28. }
  29. }
  30. }
  31. }

在为后面的视图获取数据时,用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的指示。如果数据获取失败,同样有必要展示一些全局的错误提醒。