基本区别
- 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) {...}
})