Vue2原码之Object的变化检测
目的
买了本《深入检出Vue》,来来回回看了四五次放下了四五次,学得也比较迷迷糊糊的,果然代码还是得手敲,不然根本看不懂。分析原码主要是学习,写博客主要是进行巩固及后续复习,原码能学习什么呢?我主要学习是思考问题的思路和方法。会根据书本进行说明,但并不是照本宣科,因为照着敲的时候你也会有很多疑问,根据我自己对书本的理解和其中的疑问进行分析,争取做到婴儿级别的说明(看了要思考)。
学习工具
没有什么花里胡哨的,直接浏览器的F12控制台足够(目前),个人在验证一些问题的时候经常在控制台进行处理比较结果是否符合预期。但是还是推荐VS Code来写代码(香)。
追踪变化
主要针对Vue2.x进行分析,Vue3.0重写了这部分,本着思想永不过时的理念,就分析Vue2中的思想。
怎么知道对象中的值的变化和值的获取呢
主要通过对象的defineProperty方法,可以拦截对象某个属性的获取或设置进行一些操作,具体可以在MDN上查看详细说明。请看代码,直接在代码中进行分析说明。
let obj = {
name: "张三疯",
age: 18,
};
// 拦截obj的name属性
defineReactiove(obj, "name", obj["name"]);
// 获取obj.name
console.log(obj.age); // 不会触发get拦截 -- 输出 18
console.log(obj.name); // 触发get拦截 -- 输出 获取拦截 张三疯
obj.age = 58; // 不会触发set拦截 -- 无输出
obj.name = "李小四"; // 触发set拦截 -- 输出 设置拦截
// 定义函数来拦截对象的某个键值
function defineReactiove(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
console.log("获取拦截");
return val;
},
set(newVal) {
console.log("设置拦截");
val = newVal;
},
});
}
obj的key会在获取时先进入get,在拦截语句console后返回对应的值;对该属性进行赋值的时候先进入set,形参为赋值的参数,运行拦截语句console后进行设置新的值。
如上运行代码如下图:
分析(仅个人)
根据如上结果,只会对绑定了的key进行监听,并不能监听为绑定的key的获取和设置变化。如果要对所有的属性进行拦截,需要枚举对象的key然后进行绑定。并且可以看出Vue的某个特点,对象新增属性和删除属性是没有被拦截的,所以定义的时候需要先在data设置好某些属性或是调用vm.$set和vm.$delect。
proxy拦截(钙中钙版本)
简要对比下和proxy区别,自己在开发中也有用到这个类型的数据来完成某些特定情况下的需求。
let obj = {
age: 18,
};
let handleProxy = {
get(obj, prop) {
console.log(obj, prop, "获取拦截");
return obj[prop]; // 返回对应的值
},
set(obj, prop, newVal) {
console.log(obj, prop, "设置拦截");
obj[prop] = newVal; // 设置对应的值
return newVal;
},
deleteProperty(obj, prop) {
console.log(obj, prop, "删除");
delete obj.name; // 删除对应的键
return true;
}
};
obj = new Proxy(obj, handleProxy);
console.log(obj.age); // 输出 {age: 18} "age" "获取拦截" 18
obj.age = 19; // 输出 {age: 18} "age" "设置拦截"
obj.name = "张三疯"; // {age: 19} "name" "设置拦截"
console.log(obj); // Proxy {age: 19, name: "张三疯"}
delete obj.name; // {age: 19, name: "张三疯"} "name" "删除"
console.log(obj) // Proxy {age: 19}
运行结果如下图:
对比proxy的拦截分析
proxy可以拦截到新增的属性,如果对删除拦截需要在deleteProperty中进行拦截。由此可见,Vue3.0改修后的拦截是不需要在进行主动触发响应绑定的,因为都满足拦截的条件了。
虽然拦截了,但是拦截的主要目的没有做到,将拦截的依赖收集起来,后续改动后将改动分发到各个依赖对应的目标。
下期预告:依赖收集及依赖(这部分有点难懂,且强关联,书本上没有给你验证的,需要分析后进行验证)
如有疏漏或错误,还望指正,一同成长,一同进步。