ref 和 reactive 都是用来定义响应式数据的。
Reactive 是 Vue 3 的根基。返回对象的响应式副本,响应式转换是 “深层” 的 —— 它影响所有嵌套 property。返回 Proxy 对象,不等于原始对象。建议只操作 Proxy 对象,不要操作原始对象。
官方建议,对来自于服务器的数据或者注定要响应式的数据执行 reactive 之前,最好不要用临时变量储存原始数据,因为没有意义,而且两个变量容易让初学者引起误操作。
通常使用 reactive() 来创建一个响应式的对象或数组,这样的对象或数组状态都是默认深层响应式的,无论嵌套多深,都能跟踪到。
但他也有局限性,就是只对对象类型有效,对基本数据类型无效,并且假如用一个新对象替换了原来的旧对象,那么原来的旧对象会失去响应性。
Ref 说白了就是 reactive({ value: 原始数据 }),ref 允许我们创建一个任意类型的响应式的 ref 对象,在使用时需要带上.value。在模板中使用 ref 对象时,假如 ref 位于顶层,就不需要使用 value,它会自动解包。但如果 ref 对象是作为一个属性声明于对象之中,在模板中进行运算时仍然要使用.value。
为什么似乎 Proxy 已经解决所有问题,还要有 ref API 呢?
因为 ES 的 Proxy API 是为引用数据类型服务的,它无法为基本数据类型提供代理。如果强行代理,Vue 会有提示:value cannot be made reactive: 30。
那么为什么 Vue2 的 defineproperty 并没有区分基本数据类型和引用数据类型呢?
因为 defineproperty 就是 Object 的静态方法,它只是为对象服务的,甚至无法对数组服务,因此 Vue 2 弄了一个 data 根对象来存放基本数据类型,这样无论什么类型,都是根对象的 property,所以也就能代理基本数据类型。
而 Proxy 能对所有引用类型代理,Vue 3 也不再用 data 根对象,而是一个个的变量,所以带来了新问题,如何代理基本数据类型呢?并没有原生办法,只能构建一个 { value: Proxy Object } 结构的对象,这样Proxy 也就能代理了。
问题来了,同样是响应式结构,ref 跟 reactive 的区别是什么?
1、 ref 多用来定义基本数据类型(也可以定义对象,内部会自动通过 reactive 转为代理对象),而 reactive 只能用来定义对象数组类型
2、 ref 操作数据需要 .value,reactive 操作数据不需要 .value
3、 ref 通过 Object.defineProperty() 的 ge t和 set 来实现响应式, reactive 通过 Proxy 来实现响应式,并通过 Reflect 操作源对象内部的数据
对于引用类型,什么时候用 ref,什么时候用 reactive?简单说,如果你只打算修改引用类型的一个属性,那么推荐用 reactive,如果你打算变量重赋值,那么一定要用 ref。