当前位置: > > > Vue.js - 路由 vue-router 的使用详解9(导航前、后自动获取数据)

Vue.js - 路由 vue-router 的使用详解9(导航前、后自动获取数据)

    我们常常需要在通过路由进行跳转后,根据传递过来的参数去请求服务器数据。而这个数据请求操作可以放在导航完成前,也可以放在导航完成后。下面对这两种情况分别进行演示。

一、导航完成之前获取数据

1,效果图

  • 通过点击首页面的链接跳转到详情页,跳转时还会携带有具体的 id 值。
  • 详情页需要先根据 id 获取到对应数据后,再进行跳转。(即页面渲染发生在页面请求之后)
        

2,样例代码

(1)首页代码(index.vue)很简单,这里我使用 params 方式传递参数。
<template>
    <div>
      <button @click="gotoDetail(101)">文章1</button>
      <button @click="gotoDetail(102)">文章2</button>
      <button @click="gotoDetail(103)">文章3</button>
    </div>
</template>

<script>
export default {
  name: 'index',
  methods: {
    gotoDetail(id) {
      this.$router.push({
        name:'detail',
        params:{id: id}
      });
    }
  }
}
</script>

(2)而详情页(detail.vue)中,我们在 beforeRouteEnter() 这个钩子函数中获取数据,等数据获取成功后再执行导航。
<template>
  <div>
    <h3>ID:{{ $route.params.id }}</h3>
    <h3>结果:{{ result }}</h3>
  </div>
</template>

<script>
  export default {
    name: 'detail',
    data () {
      return {
        result: ""
      }
    },
    //路由进入前调用
    beforeRouteEnter (to, from, next) {
      //传递过来的参数
      var id = to.params.id;
      //使用setTimeout模拟数据获取(等待2秒返回)
      setTimeout(function(){
        next(vm => {
          vm.result = "这个是id=" + id + "的数据";
        })
      }, 2000);
    }
  }
</script>

二、导航完成之后获取数据

这个逻辑同上面的刚好相反:
  • 我们先完成导航,然后再去请求数据。
  • 同时在数据获取期间会显示一个 loading 指示器。数据返回后 loading 消失,并在页面上显示结果。
       

首页代码和之前一样,没有变化。主要是详情页这边的实现方式由几种,分别如下。

1,在 created() 方法中请求数据

(1)我们可以直接在组件的创建完毕方法(created)中去请求数据。注意:这个只适用于没有使用 keep-alive 进行缓存的情况。
<template>
  <div>
    <div class="loading" v-if="loading">
      加载中....
    </div>
    <div>
      <h3>ID:{{ $route.params.id }}</h3>
      <h3>结果:{{ result }}</h3>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'detail',
    data () {
      return {
        loading: false,
        result: ""
      }
    },
    //组件创建完后调用
    created () {
      this.loading = true;
      //传递过来的参数
      var id = this.$route.params.id;
      //使用setTimeout模拟数据获取(等待2秒返回)
      var that = this;
      setTimeout(function(){
        that.loading = false;
        that.result = "这个是id=" + id + "数据";
      }, 2000);
    }
  }
</script>

<style>
  .loading {
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100px;
    height: 40px;
    line-height: 40px;
    background-color: #222222;
    color: white;
    text-align: center;
  }
</style>

(2)如果用到了 keep-alive,那么我们还需要使用 watch 监测路由变化,如果有变化再次去获取数据。否则只有第一次打开页面时会去请求。
<template>
  <div>
    <div class="loading" v-if="loading">
      加载中....
    </div>
    <div>
      <h3>ID:{{ $route.params.id }}</h3>
      <h3>结果:{{ result }}</h3>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'detail',
    data () {
      return {
        loading: false,
        result: ""
      }
    },
    methods:{
      fetchData () {
        this.loading = true;
        //传递过来的参数
        var id = this.$route.params.id;
        //使用setTimeout模拟数据获取(等待2秒返回)
        var that = this;
        setTimeout(function(){
          that.loading = false;
          that.result = "这个是id=" + id + "数据";
        }, 2000);
      }
    },
    //组件创建完后调用
    created () {
      this.fetchData()
    },
    watch: {
      //监听路由变化,获取数据
      '$route' : 'fetchData'
    }
  }
</script>

2,在 beforeRouteEnter() 这个钩子函数中请求数据

和最开始的样例不同的是,我们这次在导航完成之后(next 回调)再去调用相关方法请求数据。(这种方式不受 keep-alive 缓存影响)
<template>
  <div>
    <div class="loading" v-if="loading">
      加载中....
    </div>
    <div>
      <h3>ID:{{ $route.params.id }}</h3>
      <h3>结果:{{ result }}</h3>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'detail',
    data () {
      return {
        loading: false,
        result: ""
      }
    },
    methods:{
      fetchData () {
        this.loading = true;
        //传递过来的参数
        var id = this.$route.params.id;
        //使用setTimeout模拟数据获取(等待2秒返回)
        var that = this;
        setTimeout(function(){
          that.loading = false;
          that.result = "这个是id=" + id + "数据";
        }, 2000);
      }
    },
    //路由进入前调用
    beforeRouteEnter (to, from, next) {
      next(vm => {
        //导航完毕后再去请求数据
        vm.fetchData();
      });
    }
  }
</script>
评论1
  • 1楼
    2018-10-22 10:27
    你的寒王

    作者提供一下案例下载吧

    站长回复

    这个就是完整的代码啊,你搭好项目,把代码复制进行就可以了。