// 传⼊对象应该是⼀个⾮null的object
const isObject = v => typeof v === 'object' && v !== null
function reactive(obj) {
// reactive()只接受⾮null的object
if (!isObject(obj)) {
return obj
}
return new Proxy(obj, {
get(target, key) {
// Reflect⽤于执⾏对象默认操作,更规范、更友好
// Proxy和Object的⽅法Reflect都有对应
// http://es6.ruanyifeng.com/#docs/reflect
const res = Reflect.get(target, key)
console.log(`获取${key}:${res}`)
// 依赖搜集
// track(target, key)
// 判断res是对象,递归处理它
return isObject(res) ? reactive(res) : res
},
set(target, key, value) {
const res = Reflect.set(target, key, value)
console.log(`设置${key}:${value}`)
// 依赖触发
// trigger(target, key)
return res
},
deleteProperty(target, key) {
const res = Reflect.deleteProperty(target, key)
console.log(`删除${key}:${res}`)
// 依赖触发
// trigger(target, key)
return res
}
})
}
// 测试
const state = reactive({ foo: 'foo' })
// 获取
state.foo // ok
// 设置已存在属性
state.foo = 'fooooooo' // ok
// 设置不存在属性
state.dong = 'dong' // ok
// 删除属性
delete state.dong // ok
使用proxy好处
- 不需要遍历
- 懒处理, 延迟到运行时,初始化速度很快,
- 语言级别支持数组的响应式,vue2需要覆盖元素组方法 额外处理
push pop shift unshift splice revers sort
- 新增或者删除属性无法监听,需要使用特殊api
vue.set() vue.delete()
- vue2不支持Map、Set、Class等数据结构;vue3的proxy很好的支持了以上问题
vue2.7是一个自带composition api
的vue2