开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情
Proxy
代理对象,新的api,就像是中介一样,这个东西确实可以帮你做很多事,当前也需要消耗一点点性能,但是这个中介是不可或缺的 首先有如下对象
let obj = {
name: "石头",
list: [1, 2, 3]
}
然后将对象交给一个叫reactive的方法,就可以得到一个响应式的对象,这个方法里就是使用es6新特性proxy,这个类接收两个参数,第一个是目标对象,也可以叫源对象,第二个是代理规则,代理的属性有很多,这里主要用的就是读和写还有删除,首先拦截一下get方法,在get方法里trak一下,相应数据结构为map结构,使用这个key当key,然后存起来,等改这个对象的时候直接trigger一下,触发对应的更新函数
set 里有个小细节,就是当改变了对象属性值发生变化或者有新增属性时才触发更新,因为数组那个东西push一个东西时不光加了一个元素,长度属性也会变,从而导致触发两次更新,当是没关系,这个更新最后只会执行一次,再他里面处理了 设置新的属性的时候也要尝试一下代理。因为这个属性值可能是一个对象 get 里有个小细节,就是获取属性值时,这个值可能又是一个对象,但不一定是代理对象,所以要尝试代理一下这个对象,是对象就代理一下,不是就算了
const handler = {
set (taget, key, value, receiver) {
trigger()
return Reflect.set(taget, key, value, receiver)
},
get (taget, key, receiver) {
return reactive(Reflect.get(taget, key, receiver))
},
deleteProperty (target, key) {
return Reflect.defineProperty(target, key)
}
}
function reactive (taget) {
if (!isObject(taget)) {
return taget
}
let observeb = new Proxy(taget, handler)
return observeb
}
如下小案例 每次处理一个代理对象都要缓存一下,避免同一个对象被代理多次。然后假如说赋值给代理对象一个属性,而这个值是一个已经代理的对象,那么好,直接返回这个对象。
// 存代理对象
const toProxy = new WeakMap()
// 存代理前的对象
const toRow = new WeakMap()
function trigger () {
console.log('shi图更新')
}
function isObject (taget) {
return typeof taget === 'object' && taget !== null
}
const handler = {
set (taget, key, value, receiver) {
trigger()
return Reflect.set(taget, key, reactive(value), receiver)
},
get (taget, key, receiver) {
return reactive(Reflect.get(taget, key, receiver))
},
deleteProperty (target, key) {
return Reflect.defineProperty(target, key)
}
}
function reactive (taget) {
if (!isObject(taget)) {
return taget
}
// 如果这个值代理过了,直接走缓存
const proxyed = toProxy.get(taget)
if (proxyed) {
return proxyed
}
// 如果这个值就是代理对象,直接返回好了
if (toRow.has(taget)) {
console.log('zoule')
return taget
}
let observeb = new Proxy(taget, handler)
toProxy.set(taget, observeb)
toRow.set(observeb, taget)
return observeb
}
let obj = {
name: "石头",
list: [1, 2, 3]
}
let r = reactive(obj)
let p = reactive(obj.list)
r.b = p;