Vue 3 响应式系统主要基于 JavaScript 的 Proxy
API 来实现。
Proxy
可以拦截对对象的操作(如 get
、set
),从而为 Vue 实现自动追踪对象的变化并触发视图更新。
Proxy:
Proxy
是 ES6 引入的新特性,允许你创建一个代理对象,这个对象可以拦截并定义对原始对象的基本操作(例如属性读取、设置、删除等)。
Proxy
可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
API参考:ES6 入门教程
Reflect:
Reflect
是与 Proxy
一同引入的,它提供了一些与对象操作相关的静态方法,比如 Reflect.get()
和 Reflect.set()
。这些方法和与Proxy
捕获器中的行为一致。
Reflect
可以避免我们手动调用目标对象的方法,使代码更简洁和安全。
API参考:ES6 入门教程
// 原对象
let toProxy = new WeakMap()
// 对象代理
let toRow = new WeakSet()
function isObject(val){
return typeof val === 'object' && val !== null
}
function reactive(target){
return createReactiveObject(target)
}
function createReactiveObject(target){
if(!isObject(target)) {
return target
}
// 防止被多次代理
let proxy = toProxy.get(target)
if(proxy) {
return proxy
}
// 防止被再次代理
if(toRow.has(target)){
return target;
}
let baseHandler = {
get(target , key , receiver) {
console.log("读取");
// 防止无限递归
let result = Reflect.get(target,key)
// 按需递归
return isObject(result) ? reactive(result) : result
},
set(target, key , value , receiver) {
console.log("修改");
// 键值修改
let result = Reflect.set(target, key , value ,receiver)
// 按需递归
return isObject(result) ? reactive(result) : result
}
}
// 对象代理
let observed = new Proxy(target,baseHandler)
toProxy.set(target,observed)
toRow.add(observed,target)
return observed
}
let obj = {
a: 1,
b: 2,
c: {
n: 3
},
d: ['a','b','c']
}
let proxy = reactive(obj)
proxy.e = 8