梳理Vue2.0双向绑定的实现原理

Vue.js 最显著的功能就是响应式系统,它是一个典型的 MVVM 框架,模型(Model)只是普通的 JavaScript 对象,修改它则视图(View)会自动更新。这种设计让状态管理变得非常简单而直观

Vue的MVVM模型示意图

vue-mvvm.png

Vue数据响应原理图

vue-data.png

实现MVVM通用方式

要实现mvvm的双向绑定,就必须要实现以下几点:
1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm入口函数,整合以上三者

整体感知virtual DOM

virtual DOM分为三个步骤:
1.createElement(): 用 JavaScript对象(虚拟树) 描述 真实DOM对象(真实树)
2.diff(oldNode, newNode) : 对比新旧两个虚拟树的区别,收集差异
3.patch() : 将差异应用到真实DOM树

有的时候 第二步 可能与 第三步 合并成一步(Vue 中的patch就是这样)

Vue的实现原理总结

  1. 首先,在实例化的过程中,把一个普通 JavaScript 对象传给 Vue 实例的 data
    选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
  2. Dep 是一个依赖收集器。data 下的每一个属性都有一个唯一的 Dep 对象,在 get 中收集仅针对该属性的依赖,然后在 set 方法中触发所有收集的依赖。
  3. 在Watcher中对表达式求值,从而触发数据的get。在求值之前将当前Watch实例设置到全局,使用pushTarget(this)方法。
  4. 在get()中收集依赖,this.subs.push(sub),set的时候触发回调Dep.notify()。
  5. Compile中首先将template或el编译成render函数,render函数返回一个虚拟DOM对象(将模板转为 render 函数的时候,实际是先生成的抽象语法树(AST),再将抽象语法树转成的 render 函数)
  6. 当 vm._render 执行的时候,所依赖的变量就会被求值,并被收集为依赖。按照Vue中 watcher.js 的逻辑,当依赖的变量有变化时不仅仅回调函数被执行,实际上还要重新求值,即还要执行一遍
  7. 如果还没有 prevVnode 说明是首次渲染,直接创建真实DOM。如果已经有了 prevVnode 说明不是首次渲染,那么就采用 patch 算法进行必要的DOM操作。这就是Vue更新DOM的逻辑。
() => {
  vm._update(vm._render(), hydrating)
}
    这实际上就做到了 re-render,因为 vm._update 就是开头所说的虚拟DOM中的最后一步:patch

详细表述

图片来源: Vue2.1.7源码学习__HcySunYang

Paste_Image.png

参考资料

Vue2.1.7源码学习
Vue 源码解析:深入响应式原理
重复造轮子:从0开始实现Vue数据绑定

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

推荐阅读更多精彩内容

  • 这方面的文章很多,但是我感觉很多写的比较抽象,本文会通过举例更详细的解释。(此文面向的Vue新手们,如果你是个大牛...
    Ivy_2016阅读 15,450评论 8 64
  • 源码版本:v2.1.10 分析目标 通过阅读源码,对 Vue2 的基础运行机制有所了解,主要是: Vue2 中数据...
    NARUTO_86阅读 12,406评论 6 26
  • 我的github: vue双向绑定原理 MVC模式 以往的MVC模式是单向绑定,即Model绑定到View,当我们...
    KlausXu阅读 45,252评论 7 90
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,083评论 0 29
  • 双向数据绑定,我们首先来看数据改变如何触发页面的刷新。首先通过Object.defineProperty( )对v...
    209bd3bc6844阅读 1,791评论 0 1