Vue MVVM 原理实现

核心原理

MVVM 模型


    MVVM 双向数据绑定, 数据驱动视图

    Vue 实现 MVVM 采用 数据劫持 + 发布订阅模式 :

    当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用Object.defineProperty 把这些 property 全部转为 getter/setter

    Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

    这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。

    每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

响应式原理

Object.defineProperty(obj,prop,descriptor)

        obj    要定义属性的对象。

        prop  要定义或修改的属性的名称或 Symbol。

        descriptor  要定义或修改的属性描述符

    descriptor 中一些属性描述符

    对象里目前存在的属性描述符有两种主要形式:数据描述符 和 存取描述符。数据描述符 是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符  是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者

    这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty() 定义属性时的默认值):

        configurable: 是否可以配置(修改)以及是否可以删除, 默认为 false

        enumerable:是否可以遍历,默认为 false

    数据描述符还具有以下可选键值:

        value

        该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

        writable

        当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。默认为 false。

    存取描述符还具有以下可选键值:

        get

        属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为 undefined

        set

        属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。默认为 undefined


实现简单的 Vue    

    实现一个简单的 MVVM 大概分为三个步骤:1. 数据劫持,观察数据变化;2. 模板编译;3. Watcher 根据数据变化 通知 watcher ,使相关的组件重新渲染

MVVM

    1 new MVVM

        MVVM 作为连接 Complie 和 Observer 的 桥梁而存在。

myVue.js

    2. 数据劫持

        遍历 data 内的所有数据, 将他们转 为 set 和 get 的形式。 

observer.js

    3. 模板编译

        将模板中的所有含 data 中的数据,形式如 {{ a }}, v- model = 'a ',全部替换成 data 中的 数值,并且在这个阶段给每个data 中的数据添加 watcher,当该值 发生变化的时候,通知 watcher 进行 更新。

compile.js

    4. watcher

        给模板中的所有含 data 中的数据 添加一个 watcher,当这个数据发生变化的时候,触发 watcher,将模板中的 数据进行更新。

watcher.js

    5. 发布订阅

        订阅 模板中同一个 data 所对应的所有 watcher, 当这个数据改变时候,通知这个数据对应的所有 watcher, 进行更新。

dep.js


运用

总结

    Vue MVVM 采用 数据劫持 + 发布订阅的方式

    首先 将 data 中的数据 全部转换 成 set 和 get 的形式; 再编译模板,将模板中的 {{}} , v-XX 中的变量 替换成 data 中的数据;

    在 编译模板的过程中,给 每一个模板中的变量增加一个 watcher,这个 watcher 有 数据变化时所对应的将 模板中的数据 替换为最新的数据的 处理函数,将这个 watcher 添加到 这个变量订阅 的 数组中,一个变量对应一个 wathcer 数组;

    当数据发生变化,触发 set 方法,在 set 中 发布 该数据 对应的 watcher 数组,依次执行 watcher,更新 模板中的数据。

    收获: 理解 发布订阅模式的 实际应用。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。