《Vue.js设计与实现》 读书笔记
本文最后更新于:2022年4月22日 上午
第五章 非原始值的响应方案
理解 Proxy 和 Reflect
reflect 的方法都和 proxy 是对应的,在 proxy 中使用 reflect 来进行操作可以保证 this的指向正确
如
const obj = {
foo: 1,
get bar() {
return this.foo
}
}
const p = new Proxy(obj, {
get(target, key, receiver){
tarck(target, key);
return Reflect.get(target, key, receiver);
}
})
p.bar
当我们使用代理对象p
访问bar 的时候,这里的 receiver
就是 p
,这样的话,bar
的this
指向就正确了,冲洗建立起了依赖关系
JavaScript 对象及Proxy 的工作原理
需查看 ECMAScript 中的规范
以下是 阮一峰 老师的使用方式
https://es6.ruanyifeng.com/#docs/proxy
删除对象中的属性
代理 deleteProperty(target, key)
,并且在删除时需要 使用 has 来判断是否自身的属性,如果是且删除成功才需要触发更新,传入DELETE
类型
如何代理 Object (对象)
拦截 in 操作符
如下对 对象使用了in操作符
effect(() => {
'foo' in obj
});
查看 ECMAScript 规范后会发现会调用对象的内部方法 [[HasProperty]]
,它的内部方法是has
,因此可以在 Proxy
中代理 has
来对in
操作符进行拦截,建立起依赖关系
拦截 for…in
查看文档后,发现实现最终会调用 Reflect.ownKeys(obj)
来获取对象自身拥有的键,因此可以对对象在Proxy
中进行ownKeys
的拦截
const INERATE_KEY = Symbol();
const p = new Proxy(obj, {
ownKeys(target){
tarck(target, INERATE_KEY);
return Reflect.ownKeys(target);
}
})
这里需要注意的是,在进行追踪的时候,通过了INERATE_KEY
来作为key进行跟踪,这是因为,get
和set
都能够清楚的知道key
名,而在for...in
遍历时,没有具体的key名来作为标识,因此需要构造出一个唯一的key
因此在响应的时候也应该触发它
trigger(target, INERATE_KEY);
思考,如果给对象新增一个属性,该如何重新让福州用函数重新执行
p.bar = 2;
合理地触发响应
如果新值和旧值都一致,则不需要触发更新 (在 set 时先获取一次值进行判断)
避免 NaN 等情况
(old !== newVal && (oldVal === oldVal || newVal === newVal)){ trigger(target, key, type); }
设置两个响应式变量(A, B),将(B)的原型设置为响应式变量A,再通过B去修改原型上的属性,会触发两次更新,(set时需要判断
(target === receiver.raw)
如果相等才触发更新)
浅响应和深响应
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。