开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
说点题外话
上一篇说了Vue3更换底层响应式之后为什么解决了vue2对象新增属性和数组下标不能侦听的缺点,因为Proxy是侦听整个对象,而Object.defineProperty是侦听对象的属性,并且Object.defineProperty本身是可以侦听数组下标的,但是vue2舍弃了。
说正文
总结版本
着急小伙伴直接看这里,因为现在日常工作和面试还是使用vue2的比较多,所以这里还是说vue2的响应式原理
Vue2的响应式是采用数据劫持结合发布订阅模式实现的,通过Object.defineProperty劫持各个属性的getter和seter,在数据发生变化的时候通知各个订阅者,触发相应的回调完成数据的响应式。
详细版本
看完上面的简洁总结版本之后再具体说说
先看一张图片方便我们快速理解我接下来写的东西
- 首先在new Vue实例的时候,data数据会进入到
Observe
里面进行监听 - 一个data属性就会创建一个
dep
对象,每个dep对象里都存放着一个watcher
Compile
解析模板的时候除了创建watcher对象,还会初始化一个View
也就是页面上展示的- 当我们修改data里面的数据,Observe就会侦听到数据的改变,调用data对应的dep对象的notify遍历所有的watcher对象,调用watcher对象的update函数,进行view页面数据的更新。
下面让我们详细讲解一下监听器Observer
、订阅器Dep
、订阅者Watcher
、解析器Compile
分别做了什么。
监听器Observe
Observe的主要作用就是监听我们的data数据是否有改动,有改动将会通知dep对象。内部是使用Object.defineProperty劫持各个属性的getter和setter。
我这里就简单的模拟一下内部是如何实现的
/**
* 循环遍历data对象的每个属性
*/
function observable(obj) {
if (!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach((key => {
defineReactive(obj, key, obj[key])
})
return obj;
}
/**
* 将对象的属性用 Object.defineProperty() 进行设置
*/
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`${key}属性被读取了...`);
return val;
},
set(newVal) {
console.log(`${key}属性被修改了...`);
val = newVal;
}
})
}
说再见
关于vue2和vue3响应式的优缺点和底层原理就说到这,下一篇我就开始从正式入门vue3了
难忘今宵
常接吻可以更长寿吗?
接吻不仅仅可以促进人体肌肉的运动,还能促进人体分泌大量的激素物质,从而增强人体自身的免疫系统,并且经科学研究,常接吻的人要比不常接吻的人活得更长久。