深入 Vue 的一些实现原理
2023-03-22· 8min
#响应式
#实现方式:Proxy + Reflect
#Proxy
- Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义
- 优点:
- 直接监听对象而非属性
- 可以监听数组变化
- 返回并操作的是个新对象
- 缺点:
- 浏览器兼容性问题,且无法用 polyfill磨平
- 浏览器兼容性问题,且无法用
#Reflect
- 使用 Reflect在Proxy内部调用对象的默认行为
- 优势
- Reflect对象拥有Proxy对象具有的代理方法,并以静态方法的形式存在
- 使对象操作更加合理,如定义不存在属性时不会报错而是返回 false
- 使对象操作都变成函数行为
#简单实现
function reactive(obj) {
if (typeof obj !== "object" && obj !== null) {
return obj;
}
const p1 = new Proxy(obj, {
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);
console.log(`get[${key}]`, res);
return typeof res === "object" ? reactive(res) : res;
},
set(target, key, value, receiver) {
const res = Reflect.set(target, key, value, receiver);
console.log(`set[${key}]`, value);
return res;
},
deleteProperty(target, key) {
const res = Reflect.deleteProperty(target, key);
console.log(`delp${key}]`, res);
return res;
},
});
return p1;
}
var r1 = reactive({
kk: { k: 1 },
});
console.log(`${r1.kk.k}\n\n`); // 1
r1.kk.k = 2;
console.log(`\n`);
console.log(`${r1.kk.k}`); // 2
#参考文献
#实现方式:Object.defineProperty()
#Object.defineProperty()
- Object.defineProperty()静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象
- 优点:
- 兼容性好,支持 IE9
- 缺点:
- 无法监听数组的变化
- 无法监听对象动态新增的属性
#简单实现
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`get[${key}]: ${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`set[${key}]: val[${val}] newVal[${newVal}]`);
val = newVal;
}
},
});
}
var o2 = { k: 1 };
defineReactive(o2, "k", o2.k);
setTimeout(() => {
o2.k = "3";
}, 2000);