ref和reactive的区别

49 阅读2分钟

基本区别

  • ref 用来包装基本类型(数字,字符串,布尔等)
  • reactive 用来包装对象和数组
  • ref -> .value
  • reactive -> 直接访问字段

ref:适合基本类型

const count = ref(0)

//读取:
count.value

//修改:
count.value++

ref的特点:

  • 本质是一个拥有value属性的对象
  • 用来让基本类型变成响应式
  • 在模板里不需要.value,模板会自动解包

reactive:适合对象、数组、字典

const form = reactive({
  username: "",
  password: "",
})

读取、修改都直接操作:

`form.username = "yeye"`

不需要.value

reactive的特点:

  • 用proxy实现的深层响应式
  • 内部所有字段都是响应式(深层自动追踪)
  • 不能用来替换整个对象

reactive 不能整体替换,而 ref 可以

reactive 错误写法:

form =  { username: "a" } // reactive 会失效

你以为数据是响应式的,但 Vue 实际没有跟踪到它的变化,导致页面不更新 / watch 不触发 / 依赖不重新计算。

vue 的 reactive本质是用proxy包装对象,让 “对象内部属性的get/set” 都能被追踪

但vue只能追踪属性修改,不能追踪“变量本身被重新赋值”

也就是说,reactive追踪的是对象内部属性,而不是变量重新赋值,而ref虽然也用proxy,但追踪的不是变量本身,而是ref对象的.value属性

const form = ref({})     // form.value 指向对象
form.value = { username: "123" } // 可以整体替换

reactive的追踪方式

const obj = reactive({a:1})

vue会做这样的proxy:

Proxy(target_obj, {
  get(target, key) {...},
  set(target, key, value) {...}
})

所以 Vue 能知道:

  • obj.a 被读取
  • obj.a 被修改

但 Vue 无法追踪

obj = { a: 2 }  // 这只是变量赋值,和 Proxy 无关!

这是为什么 reactive “整体替换”会失效。

变量被重新赋值,不会触发 Proxy 的 set,因为 Proxy 根本管不到这个操作。

Proxy 只能追踪属性,不追踪变量本身。

ref的追踪方式

假设你写:

const count = ref(0)

Vue 实际做的是:

count ----> { value: 0 } ← 被 Proxy 包裹

也就是说 ref 返回的是一个对象,而这个对象的结构是固定的:

Vue 会给这个 { value } 做 Proxy:

Proxy({ value: 0 }, {
  get(target, key) {...},
  set(target, key, value) {...}
})