22

Vue同一路由跳转页面不刷新解决方案及注意事项

 3 years ago
source link: https://www.daozhao.com/9857.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

默认情况跳转至同一个路由地址(path相同,即使params或者query不同也算同一个)的话,只是浏览器url变了,其它是不会发生任何变化,这就是网友常说的“同一页面跳转,路由变了但是页面不刷新”。 我们可以写两个测试页面

// goNext.vue
<template>
  <section>
    <button @click="goNext">跳转至自身</button>
    <button @click="goBack">跳转至goBack</button>
  </section>
</template>
<script>
  export default {
    name: 'goNext',
    mounted() {
      console.log('组件生命周期 mounted', 'goNext');
      this.showInfo();
    },
    beforeDestroy() {
      console.log('组件生命周期 beforeDestroy-> ', 'goNext');
    },
    beforeRouteEnter(to, from, next) {
      console.log('路由生命周期 beforeRouteEnter-> ', 'goNext');
      next();
    },
    beforeRouteLeave(to, from, next) {
      console.log('路由生命周期 beforeRouteLeave-> ', 'goNext');
      next();
    },
    methods: {
      goNext() {
        this.$router.push({
          path: '/goNext',
          query: {
            info: Date.now(),
          }
        })
      },
      goBack() {
        this.$router.push('goBack')
      },
      showInfo() {
        const info = this.$route.query.info || 'Default';
        this.$message.info(info);
      },
    },
    watch: {
      '$route'(to) {
        console.log('watch $route', to.query.info, to);
      },
    }
  }
</script>
// goBack.vue
<template>
  <section>
    <button @click="goBack">退回</button>
  </section>
</template>
<script>
  export default {
    name: 'goBack',
    mounted() {
      console.log('组件生命周期 mounted', 'goBack');
    },
    beforeDestroy() {
      console.log('组件生命周期 beforeDestroy-> ', 'goBack');
    },
    beforeRouteEnter(to, from, next) {
      console.log('路由生命周期 beforeRouteEnter-> ', 'goBack');
      next();
    },
    beforeRouteLeave(to, from, next) {
      console.log('路由生命周期 beforeRouteLeave-> ', 'goBack');
      next()
    },
    methods: {
      goBack() {
        this.$router.go(-1);
      },
    }
  }
</script>

直接进入/goNext MnqYBv6.png!mobile

通过console我们可以看到先执行的是 beforeRouteEnter 然后才是 mounted ,也就是 路由的生命周期优先于组件的生命周期 。我们想要的toast在 showInfo 方法得到执行。

我们接下来再做几个路由跳转相关的测试。 0.初始态,直接刷新goNext BJRRnav.png!mobile

1.点击“跳转至自身”后url的链接地址变了,只有 watch 里面的回调执行了,其它的都没有 rmmyq27.png!mobile 所以我们想要出现toast,就只能在watch里面调用 showInfo 了。

2.如果再点击“跳转至goBack”会有什么效果呢? nMJbEf2.png!mobile

总体先后顺序肯定是先goNext再goBack。然后依然是 路由的生命周期优先于组件的生命周期 ,并且是老的先销毁,新的再加载。

3.跳转到goBack页面,我们在点击“返回”呢? bQbyy2V.png!mobile 效果和上面的第2个一样(废话)

“同一页面跳转,路由变了但是页面不刷新”这个“问题”我们只能通过watch路由来实现么? 有时我们有很多这样的同一页面再次跳转需求怎么办,给每个页面加上watch,然后把 mounted 里面的内容也在一个方法里面,然后再 mounted 里面调用该方法,并且在watch里面也调用?这当然没问题,有时不是太多了想偷点栏吗,怎么办?

这就需要用到key了

怎么弄?

<router-view :key="$route.fullPath"></router-view>

因为我们在加入了query并且里面的info是使用的时间戳,所以每次fullPath都不一样

为了对比我们可以再加入一个不带时间戳的跳转

goNextWithoutTimestamp() {
    this.$router.push({
        path: '/goNext',
    })
},

4.当我们点击“跳转至自身不带时间戳”时,结果是这样,有这种同一路由多次跳转的网友应该不陌生。 fYjyaaf.png!mobile

因为路由地址完全一样,fullPath也是一样的,上的key其实也没有任何帮助。

5.但是如果这是我们再点击之前的“跳转至自身”会有什么结果呢? MFZvI3U.png!mobile

我们可以看到组件的生命周期确实执行了,但是 路由的生命周期没有执行了 ,那样我们想在组件里面的路由钩子里面进行一些阻止跳转的逻辑就不行了。

那我们再进一步,加上全局的路由钩子看看有什么效果,全局的还会执行吗? 我们先进行这样的改动 RraQna6.png!mobile

我们先重新执行下前面第4、5个示例。 重试4 u2E77jb.png!mobile 重试5 AVfqAj.png!mobile 通过重试4、5可以发现跟4、5不同的是全局的路由钩子还是会如期执行的。

接下来我们再重试下前面的第0、1、2、3个示例吧。加上了全局路由钩子和 :key="$route.fullPath" 重试0 ue6B3eY.png!mobile 重试1 nEjQ323.png!mobile 重试2 JNbIrq.png!mobile 重试3 yuQviyI.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK