• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 数据获取

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

    • 导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
    • 导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

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


    导航完成后获取数据

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

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

    <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() {
        // watch 路由的参数,以便再次获取数据
        this.$watch(
          () => $route.params.id,
          () => {
            this.fetchData()
          },
          // 组件创建完后获取数据,
          // 此时 data 已经被 observed 了
          { immediate: true }
        )
      },
      methods: {
        fetchData() {
          this.error = this.post = null
          this.loading = true
          // replace `getPost` with your data fetching util / API wrapper
          // 用你的数据获取 util 或 API 替换 `getPost`
          getPost(this.$route.params.id, (err, post) => {
            this.loading = false
            if (err) {
              this.error = err.toString()
            } else {
              this.post = post
            }
          })
        },
      },
    }
    


    路由导航完成后,才更新 DOM,才运行组件的生命周期钩子。所以除去生命周期create()钩子外,还可以使用:beforMount()mounted()。在组合式API中,使用onBeforMount()onMounted()

    相同路由导航,即带有参数的路由。当参数变化的时候,相同的组件实例会被重复使用,所以组件的生命周期钩子会被调用。



    在导航完成前获取数据

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

    export default {
      data() {
        return {
          post: null,
          error: null,
        }
      },
      beforeRouteEnter(to, from, next) {
        getPost(to.params.id, (err, post) => {
          next(vm => vm.setData(err, post))
        })
      },
      // 路由改变前,组件就已经渲染完了
      // 逻辑稍稍不同
      async beforeRouteUpdate(to, from) {
        this.post = null
        try {
          this.post = await getPost(to.params.id)
        } catch (error) {
          this.error = error.toString()
        }
      },
    }
    

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

    上篇:过渡动效

    下篇:滚动行为