和Vue3和解的Day5--MVVM响应式原理

48 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情

说点题外话

上一篇说了Vue3更换底层响应式之后为什么解决了vue2对象新增属性和数组下标不能侦听的缺点,因为Proxy是侦听整个对象,而Object.defineProperty是侦听对象的属性,并且Object.defineProperty本身是可以侦听数组下标的,但是vue2舍弃了。

说正文

image.png

总结版本

着急小伙伴直接看这里,因为现在日常工作和面试还是使用vue2的比较多,所以这里还是说vue2的响应式原理

Vue2的响应式是采用数据劫持结合发布订阅模式实现的,通过Object.defineProperty劫持各个属性的getter和seter,在数据发生变化的时候通知各个订阅者,触发相应的回调完成数据的响应式。

详细版本

看完上面的简洁总结版本之后再具体说说

先看一张图片方便我们快速理解我接下来写的东西

image.png

  • 首先在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;
        }
    })
}

image.png

说再见

关于vue2和vue3响应式的优缺点和底层原理就说到这,下一篇我就开始从正式入门vue3了

难忘今宵

常接吻可以更长寿吗?

接吻不仅仅可以促进人体肌肉的运动,还能促进人体分泌大量的激素物质,从而增强人体自身的免疫系统,并且经科学研究,常接吻的人要比不常接吻的人活得更长久。