vue3 ref,reactive,toRef,toRefs总结

最近自己也在学习vue3,在看文档与博客的过程中,发现有有些博主的vue3关于双向绑定实现响应式有部分误解,评论区更是有人直接开喷,所以啊,自己去一个一个实践才是最靠谱的,在此分享我的实践干货。
直入主题:

ref:

<template>
  <div>
    <h3>{{ count.num }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { ref } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = ref(test);
    function add() {
      count.value.num++;
      console.log(count.value); // 12
      console.log(test); // 12
    }
    return {
      count,
      add,
    };
  },
};
</script>

点击一次增加按钮,控制台打印均为12,先别急总结,继续看

<template>
  <div>
    <h3>{{ count }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { ref } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = ref(test.num);
    function add() {
      count.value++;
      console.log(count.value); //11
      console.log(test.num);  //12
    }
    return {
      count,
      add,
    };
  },
};
</script>

这次点击增加按钮,控制台打印count值为12,test.num值仍为11
由此可见:通过ref去定义的变量,如果赋值的是原始对象本身,变量改变会影响原始对象也改变,如果赋值为原始对象的某个属性值,变量改变原始对象本身不会发生任何改变。

reactive:

<template>
  <div>
    <h3>{{ count.num }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { reactive } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = reactive(test);
    function add() {
      count.num++;
      console.log(count.num); //12
      console.log(test.num);  //12
    }
    return {
      count,
      add,
    };
  },
};
</script>

点击增加按钮控制台打印均为12,因为reactive只能赋值对象与数组类型,我们再来试试数组类型

<template>
  <div>
    <h3>{{ count[0] }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { reactive } from "@vue/reactivity";
export default {
  setup() {
    let test=[11,12,13]
    let count = reactive(test);
    function add() {
      count[0]++;
      console.log(count[0]); //12
      console.log(test[0]);  //12
    }
    return {
      count,
      add,
    };
  },
};
</script>

点击增加按钮控发现制台打印也均为12,,所以在此看来通过reactive定义的变量改变同时也会改变原始对象或数组

在不少博主哪里可以看到将return出去的变量通过扩展符号点点点解构,这样return出去的变量的属性均会被暴露,标签中可以直接引用属性。但是这样的坏处就是通过点点点以后的变量会失去响应式

<template>
  <div>
    <h3>{{ num }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { reactive } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = reactive(test);
    function add() {
      count.num++;
      console.log(count.num); //12
      console.log(test.num);  //12
    }
    return {
      ...count,
      add,
    };
  },
};
</script>

点击增加按钮控制台打印均为12,但是视图没有更新,由此可见,失去响应式的变量改变仍然可以影响原始数据改变,但是视图不会更新。那么如果解决呢?

<template>
  <div>
    <h3>{{ num }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { reactive, toRefs } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = reactive(test);
    function add() {
      count.num++;
      console.log(count.num); //12
      console.log(test.num);  //12
    }
    return {
      ...toRefs(count),
      add,
    };
  },
};
</script>

点击增加按钮控制台打印均为12,使用toRefs可以将变量恢复响应式。有朋友要问了,ref的对象可以使用扩展运算符点点点吗,博主做了测试,不行嗷,我还看见有人使用toRefs去定义:let count = toRefs(test); 博主也做了测试,这样是可以使用的,且变量改变原始数据也会改变,视图不会更新,并且控制台会有警告提示:toRefs()需要一个反应对象,但收到一个普通对象。所以还是不用为好。

toRef:

<template>
  <div>
    <h3>{{ count }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { toRef } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = toRef(test, "num");
    function add() {
      count.value++;
      console.log(count.value); //12
      console.log(test.num); //12
    }
    return {
      count,
      add,
    };
  },
};
</script>

点击增加按钮控制台打印均为12,但是视图没有更新,所以toRef定义的变量不是响应式的。但是奇怪的事情来了。

<template>
  <div>
    <h3>{{ count }}----{{ count2 }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { toRef, ref } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = toRef(test, "num");
    let count2 = ref(22);
    function add() {
      count2.value++;
      count.value++;
      console.log(count.value); //12
      console.log(test.num); //12
    }
    return {
      count,
      count2,
      add,
    };
  },
};
</script>

我发现只要改变了count2的值视图更新了,原本视图中count未更新,现在也更新了。
思考:如果定义一个其他的响应式变量可以更新视图,响应式变量改变时候视图更新,能够带动不能使视图更新的变量,视图中的值也更新吗?

<template>
  <div>
    <h3>{{ num }}----{{ count2 }}</h3>
    <button @click="add">增加</button>
  </div>
</template>

<script>
import { reactive, ref } from "@vue/reactivity";
export default {
  setup() {
    let test = {
      num: 11,
    };
    let count = reactive(test);
    let count2 = ref(22);
    function add() {
      count2.value++;
      count.num++;
      console.log(count.num); //12
      console.log(test.num); //12
    }
    return {
      ...count,
      count2,
      add,
    };
  },
};
</script>

进一步的实践,我发现如果让reactive定义的变量失去响应式,按照上例同样的操作,并不能通过改变响应式变量更新视图中的值,去带动其他不响应式变量更新视图中的值。这就很奇怪了啊。那就不存在响应式带动非响应式,因为我是在写博客过程中发现的,具体原因只能后面深究了。 待定…

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

D^Q^X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值