前言:ref和reactive是干什么用?就是把数据变成「响应式」的

Vue3中实现数据响应式,用到的是组合式API中的refreactive函数,不同的是ref函数一般定义基本类型数据,而reactive函数用于定义一个对象类型的响应式数据。

Vue2和Vue3中的响应式

vue2的响应式是通过Object.defineProperty(数据劫持)方法,针对对象和数组有两种处理:

  • 对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
  • 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持

ref函数

  1. 作用: 定义一个响应式的数据

  2. 语法: const xxx = ref(initValue)

  • 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)
  • JS中操作数据: xxx.value,因为ref 接收参数并将其包裹在一个带有 value property 的对象中返回
  • 模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>
  • 本质上,ref(0) 等于 reactive( { value:0 })

使用事项

  1. 使用ref包装之后,需要使用.value才行进行取值和赋值操作。这就导致一个结,就是在对象起属性名时,尽可能避开有value的属性名。因为会引起混淆。
  2. 响应式对象里面如果有ref包装的值类型。则Vue会实现自动拆箱,即获取值的方式是object.property,而不是object.property.value,注意:只有响应式对象会是这样,响应式数组或者Map都不能这样。
  3. 接受的数据可以是:基本类型,也可以是对象类型,基础类型靠Object.defineProperty()的get与set完成响应式,对象类型则是靠reactive函数进行辅助

使用案例

1
2
3
4
import { ref, reactive, toRef } from 'vue'
const A = ref('AliveSeven')

console.log('A的ref数据:', A)

改变A,要用.value来改变

1
2
3
A.value = 'Alice'

console.log('改变了A后:',A)

使用ref来声明对象类型时候:

1
2
3
4
5
6
const C = ref({
name : 'Nanami',
age : 77
})

console.log('C的ref数据:', C)

reactive函数

  • 作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
  • 语法:const 代理对象= reactive(源对象)

使用事项

  1. 接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
  2. js中操作不需要.value(与ref区别)
  3. reactive定义的响应式数据是“深层次的”。
  4. 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。
  5. 可以使用toRef(obj)为对象中的每一个属性创建一个ref,它可以保持对原属性的响应式链接,类似于浅拷贝
    *

ref和reactive的区别

  1. ref定义对象,在js中使用时都应该.value,如果定义的对象嵌套太深,再多一层.value太冗余,而reactive则无需.value
  2. ref定义对象类型数据,里边使用的也是reactive中的Proxy代理,不如直接使用reactive
  3. reactive不能直接定义基本类型数据,不起作用,可以将基本类型数据整体放入一个对象中,将reactive当作Vue2中的data去使用
  4. ref存在异步问题

使用案例

1
2
3
4
5
6
const B = reactive({
name: 'Alive2',
age: 22
})

console.log('B的ref数据:', B)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { ref, reactive, toRef } from 'vue'

const B = reactive({
name: 'Alive2',
age: 22,
hobby:[
{
type : "唱"
},
{
type : "跳"
},
{
type : "rap"
},
{
type : "篮球"
}
]
})

console.log('B的ref数据:', B)

// reactive定义的响应式数据是“深层次的”。
// 下面的赋值不会影响上面的结果

B.name = 'Alive3'
B.age = 99
B.hobby[3].type = "ctrl"

console.log('改变了B后:',B)