路由返回实践以及reactive/ref 原理剖析

一、beforeRouteLeave指定路由后死循环

应用场景:

当希望某页面点击左上角返回时,不按原路径返回,而是跳转到某一指定页面。

1.踩坑写法:

 beforeRouteLeave(to, from, next) {
    if (this.isBack) {
      console.log('to指定路由');
      next('/stock/inventoryLog');
    } else {
      next();
    }
 },

2.解决办法:

 beforeRouteLeave(to,from,next){
    if(this.isBack){
      const timer = setTimeout(()=>{
        this.flag = true;
        clearTimeout(timer);
      },100)
    }else{
      next()
    }
  },
  watch:{
    flag(newval){
      if(newval){
        this.isBack = false;
        this.$router.push('/stock/inventoryLog');
      }
    }
  }

3.分析原因:

导航守卫方法接收的三个参数:

  • to:即将进入的目标路由;

  • from:当前导航正要离开的路由;

  • next:

    • next():进入管道中的下一个钩子;

    • next(false):中断当前导航,如果路由改变了,那么ur地址会重置到from路由对应的地址;

    • next('/')或者next({path:'/'}):跳转到一个不同的路由地址,当前的导航被中断,然后开始一个新的导航。

4.正确写法:

  beforeRouteLeave(to,from,next){
    if(this.isBack){
      console.log('1,离开当前页面',to,from);
      if(to.path == '/stock/inventoryLog'){
        console.log('2,去到指定路由');
        next()
      }else{
        console.log('3,手动重定向路由');
        next('/stock/inventoryLog')
      }
    }else{
      next()
    }
  },

分析一下上面代码中的打印顺序呢?

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

二、vue3中reactive定义的引用类型(对象object、数组array)直接赋值的话,会导致数据失去响应式。

1.踩坑写法:

<template>
  <div>数组:{{myArr}}</div>
</template>
<script setup>
  import { reactive } from "vue";
  // 测试数组
  let myArr = reactive([]);
  setTimeout(()=>{
    let res = [1,2,3]; 
    myArr = res;  // 直接赋值
  },2000)
    
</script>

2.正确写法:

<template>
  <div>数组1:{{myArr}}</div>
  <div>数组2:{{myObj.arr}}</div>
</template>
<script setup>
  import { reactive } from "vue";
 
  let myArr = reactive([]);
  let myObj = reactive({arr:[]});
  setTimeout(()=>{
    let res = [1,2,3];
    myArr.push(...res); // 方法一
    myObj.arr = res;   // 方法二
  },2000)
    
</script>

3.分析原因:

reactive返回的是一个proxy代理的对象(Vue3通过proxy代理实现数据的响应式),直接赋值会导致该对象被覆盖,失去响应式。

测试代码:

<script>
  const { reactive, isReactive, ref, isRef } = Vue
  Vue.createApp({
    setup() {
      let arr1 = reactive([]);
      let arr2 = reactive([]);
      let arr3 = ref([]);
      console.log('初始化打印arr1',arr1,isReactive(arr1)); // 初始化打印arr1 Proxy{} true
      console.log('初始化打印arr2',arr2,isReactive(arr2)); // 初始化打印arr2 Proxy{} true
      console.log('初始化打印arr3',arr3,isRef(arr3));      // 初始化打印arr3 RefImpl{..., _value:Proxy{}, ...} true
      setTimeout(()=>{
        let res = [1,2,3];
        arr1 = res;
        arr2.push(...res);
        arr3.value = res;
        console.log('改变值后打印arr1',arr1,isReactive(arr1)); // 改变值后打印arr1 [1, 2, 3] false
        console.log('改变值后打印arr2',arr2,isReactive(arr2)); // 改变值后打印arr2 Proxy{0: 1, 1: 2, 2: 3} true
        console.log('改变值后打印arr3',arr3,isRef(arr3));      // 改变值后打印arr3 RefImpl{..., _value:Proxy{0: 1, 1: 2, 2: 3}, ...} true
      },1000)


      return {
        arr1,
        arr2,
        arr3
      }
    }
  }).mount('#app')
</script>

vue3 reactive源码如下:

补充:ref去初始化申明一个引用类型的数据,再通过.value去赋值和使用,仍然具有响应式。

疑问:为什么直接对ref.value赋值,数据仍具有响应式?

分析:在class RefImpl中,每一次的set操作,在符合条件的情况下,都会调用toReactive方法,如果是引用类型的数据,就会调用reactive方法,从而使ref.value数据具有响应式。

vue3 ref源码如下:

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值