简单聊下 Vue3 中 reactive 和 ref

介绍

众所周知,vue3 相较于 vue2 进行了很大提升,很大的一方面就是响应式原理上————使用了 Proxy。Proxy 可以先看看 阮一峰大大的教程,建议 15、16章节连起来看,那么如何去使用呢?

我们可以这样的理解,reactive 和 ref 相当于一个语法糖,使用这两个语法糖创建的变量就具备了响应式的功能,能自动的在页面和数据之间进行驱动。可能有朋友不太理解,ref 在 vue2 中不是定义操作 DOM 的节点吗?为什么这里能定义变量了,还是响应式的。这是因为 vue3 内部给它重新进行了赋能,具体还没有扒源码,大家先简单这样记下就好。

好,具体说下区别:

定义上:

  • ref - 推荐定义基础类型变量,这个时候内部是使用 Object.defineProperty 实现响应原理的,如果定义了 Object 类型变量,那么其内部还是指向 proxy 的,这点我们可以先打印看看
    简单聊下 Vue3 中 reactive 和 ref
    简单聊下 Vue3 中 reactive 和 ref

从 value 指向上我们可以看到内部 value、_value 的变更

  • reactive - 推荐使用复杂变量,如 object,可从 ref 定义复杂变量内部还是指向 proxy,或 proxy 拦截复杂对象反向推到,这里放一张 vue3 官方网站上的 reactive 定义
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

可以看到可拓展对象还是指向的 object

使用方式上:

注意:这里如果没有特指,使用范围全部在 setup 内

  • ref - 的赋值必须使用 .value,这点可从打印的图片上可以看出,那同理,取值的话也要加一个 .value,不然指向不正确,来张图:

简单聊下 Vue3 中 reactive 和 ref
简单聊下 Vue3 中 reactive 和 ref

但是 .value 取值的话一次还好,多次就比较麻烦,这里有一个简化的 api——unref,同样来张图:

简单聊下 Vue3 中 reactive 和 ref

import { unref } from 'vue';

const aa = ref('haha');
console.log('aa', aa);
console.log('aa.value prev', aa.value);
aa.value = 'houhou';
console.log('aa.value next', aa.value);
console.log('unref(aa)', unref(aa));
  • reactive - reactive 则没这么麻烦,和正常的 object 一样操作就好,没有什么 .value,同样来张图:

简单聊下 Vue3 中 reactive 和 ref

import { reactive} from 'vue';

const cc = reactive({
  a: 1,
  b: 2,
  c: 3
});
cc.a = 10;
cc.d = 12;
console.log('cc', cc);
console.log('cc.a', cc.a);
console.log('cc.d', cc.d);

可以看到正常的 object.key 这种形式,新增和修改都是能正常响应的(如更改的属性 a 和 新增的属性 d),来说说如果对它解构的话会怎样,来张图:

简单聊下 Vue3 中 reactive 和 ref

let { a } =cc;
console.log('a prev', a);
a = 15;
console.log('a next', a);
console.log('cc', cc);

可以看到,解构的变量不再具有响应式(a 改变,cc 并没变),当然这种情况用到的不多,如果我们要改变一个对象的某个属性,一般可通过 Object.assign(obj, {}) 这种形式解决,这里说他只是为了引入 toRefs 这个 api——把 reactive 解构为一组具备响应式关系的 ref,同样来张图:

简单聊下 Vue3 中 reactive 和 ref

可以看到打印出来的变量 b 已经指向了 ObjectRefImpl 这个类,并看到 ``__v_isRef:、_key、_object、value``` 这几个属性,可以简单的把它们理解为响应关联,此时 b 这个变量就和 cc 这个对象关联起来了,当改变 b 的值时,cc 同样发生了变化,这样有个好处就是,当我们在一个 reactive 里定义了很多变量时,如果在模板上一个一个 object.key 这种方式去写,会很麻烦,也不美观,这个时候就可以 toRefs 出去,直接写 key 即可,这样数据就具备了响应关联,vue 就能在数据变化时自动更新页面,我们来试下,同样上图:

简单聊下 Vue3 中 reactive 和 ref

// template
<ul>
  <li>我是 cc 对象的属性 a,{{ a }}</li>
  <li>我是 cc 对象的属性 b,{{ b }}</li>
  <li>我是 cc 对象的属性 c,{{ c }}</li>
</ul>

// setup
return {
  ...toRefs(cc)
};

最后

说得多还不如上手,大家动手练练哈哈

上一篇:Vue3:ref、reactive、toRef、toRefs的区别


下一篇:Vue3 element-plus 简单表单使用