响应式原理
Vue 的核心特性之一是响应式系统,当数据变化时视图会自动更新。
Vue 2: Object.defineProperty
Vue 2 使用 Object.defineProperty 将对象属性转换为 getter/setter:
JavaScript
function defineReactive(obj, key, val) {
const dep = new Dep()
Object.defineProperty(obj, key, {
get() {
if (Dep.target) dep.depend()
return val
},
set(newVal) {
if (newVal !== val) {
val = newVal
dep.notify()
}
}
})
}
局限性
- 无法检测对象属性的添加或删除
- 无法检测数组索引的直接赋值
- 需要使用
Vue.set/vm.$set手动处理
JavaScript
// 正确做法
this.$set(this.user, 'age', 25)
this.$set(this.arr, 0, 'new value')
Vue 3: Proxy
Vue 3 使用 Proxy 重写响应式系统:
JavaScript
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver)
track(target, key)
return typeof res === 'object' ? reactive(res) : res
},
set(target, key, value, receiver) {
const res = Reflect.set(target, key, value, receiver)
trigger(target, key)
return res
}
})
}
Proxy 的优势
- 可拦截 13 种操作,包括属性添加/删除
- 原生支持数组索引修改
- 惰性响应,嵌套对象按需代理
JavaScript
const state = reactive({ count: 0 })
state.count++ // 自动触发更新
state.newKey = 'hello' // Vue 3 可检测,Vue 2 不行
ref 与 reactive
JavaScript
import { ref, reactive } from 'vue'
// ref 用于基本类型
const count = ref(0)
count.value++
// reactive 用于对象
const state = reactive({ count: 0 })
state.count++
要点总结
- Vue 2 使用
Object.defineProperty,存在数组和动态属性检测盲区 - Vue 3 使用
Proxy,能力更强,性能更好 ref包装基本类型,reactive处理对象- 响应式是 Vue 自动更新视图的基础
📝 发现内容有误?点击此处直接编辑