本帖最后由 Clark.Pan 于 2024-1-31 17:16 编辑
前言:
ref reactive 傻傻分不清楚,相信大多数使用VUE3的同学都会有这样的疑惑,到底是该用 ref 呢还是 reactive。相信看过本文之后,您会有一个大致的判断:
相同点:
ref 和 reactive 都是 Vue3 中用来实现数据响应式的 API,ref 和 reactive 都可以用于创建一个响应式的数据。
什么是数据响应式,简单来说就是数据发生变化后,页面的渲染也会跟着发生更新。
不同点:
1. reactive 仅对引用数据类型有效(对象、数组和 Map 这样的集合类型),而对 string、number 这样的 基础数据类型 无效。ref 可以兼顾引用数据类型和基础数据类型。
2. ref 创建的是响应式数据,通常通过 `.value` 属性访问实际值;而通过 reactive 创建的是响应式对象,可以直接访问其属性或调用其方法。
3. ref 使用 `.value` 属性访问和更新值,而 reactive 是原始对象的代理(直接访问其属性或调用其方法)。因此,ref 可以重新分配给一个新对象,而 reactive 不能。个人感觉 reactive 这里类似于深拷贝,重新赋值一个新对象,新对象的地址和就对象是不同的,所以无法做到响应式。 例如下面的例子:
- <template>
- <p>{{ info }}</p>
- </template>
- <script>
- import { onMounted,reactive } from 'vue'
- export default {
- name: 'App',
- setup(){
- let info = reactive({ name: "小明",sex:"男" });
- onMounted(() => {
- info = reactive({ name: "小红",sex:"女" });
- })
- return {
- info
- }
- }
- }
- </script>
复制代码 在 onMounted 方法中当我们直接替换reactive中的对象时,会发现替换了之后页面无法更新。这也是经常说的 reactive 响应式失效的原因。最直接的解决方案就是直接对 reactive 中的属性做替换,例如:
如果是整体替换对象,可以考虑使用 Object.assign 对象的浅拷贝来完成
- let a = {"name":"小明","sex":"男"};
- let b = {"name":"小红","sex":"女"};
- Object.assign(a,b)
复制代码
但是如果对象字段发生了变化,例如:
- let a = {"name":"小明","sex":"男"};
- let b = {"name":"小红","age":"18"};
- Object.assign(a,b)
复制代码 这个时候结果并不是 b 对象完全替换 a 对象,而是合并的一个结果 { name: '小红', sex: '男', age: '18' }。这个时候如果需要的结果是 { name: '小红', age: '18' }
那么可以通过 ref 代替 reactive 来完成
- <template>
- <p>{{ info }}</p>
- </template>
- <script>
- import { onMounted,ref } from 'vue'
- export default {
- name: 'App',
- setup(){
- let info = ref({"name":"小明","sex":"男"});
- onMounted(() => {
- info.value = {"name":"小红","age":"18"};
- })
- return {
- info
- }
- }
- }
- </script>
复制代码
选择ref 还是 reactive:
个人建议如果不是因为一些特殊的原因,大多数情况下推荐使用 ref ,原因如下:
1. 如上面说的 reactive 仅对引用数据类型有效 ref 则可以兼顾引用数据类型和基础数据类型。
2. 如上面的例子所示,在更新响应时 reactive 有一定的局限性。
|
|