Vue的MVVM响应式原理介绍

321 阅读3分钟

1.主流的实现数据绑定的方法:

⽬前⼏种主流的mvc(vm)框架都实现了单向数据绑定,⽽我所理解的双向数据绑定⽆⾮就是在单向绑定的基础上给可输⼊元素(input、textare等)添加了change(input)事件,来动态修改model view,并没有多⾼深。所以,不要恐惧。

实现数据绑定的做法有⼤致如下⼏种:

  • 发布者-订阅者模式(backbone.js

  • 脏值检查(angular.js

  • 数据劫持(vue.js

发布者-订阅者模式:

⼀般通过sub, pub的⽅式实现数据和视图的绑定监听,更新数据⽅式通常做法是vm.set('property', value) ,这⾥有篇⽂章讲的⽐较详细www.html-js.com/article/Stu…,有兴趣可点这⾥这种⽅式现在毕竟太low了,我们更希望通过 vm.property= value 这种⽅式更新数据,同时⾃动更新视图。于是有了下⾯2种⽅式:

脏值检查:

angular.js 是通过脏值检测的⽅式⽐对数据是否有变更,来决定是否更新视图,最简单的⽅式就是通过**setInterval() 定时轮询检测数据变动**,当然Google不会这么lowangular只有在指定的事件触发时进⼊脏值检测,⼤致如下:

  • DOM事件,

  • 譬如⽤户输⼊⽂本,

  • 点击按钮等。( ng-click )

  • XHR响应事件 ( $http )

  • 浏览器Location变更事件 ( $location )

  • Timer事件( timeout,timeout, interval )

  • 执⾏( digest())(digest() )或( apply())

上面的2种形式做简单了解即可,重点是接下来的数据数据劫持

数据劫持:

vue.js 则是采⽤**数据劫持结合发布者-订阅者模式**的⽅式,通过 Object.defineProperty() 来劫持各个属性的settergetter ,在数据变动时发布消息给订阅者,触发相应的监听回调

2.new MVVm过程梳理:

初始化:

初始化的时候走的是1号线的部分,Compile解析初始化的内容,初始化视图,并且添加了和初始化属性个数一样的观察者Dep中。

数据变化:

如果属性发生变化,走2号线路的数据劫持,发现数据变化通知订阅器Dep中的观察者,然后订阅器通知 watcher中发生变化的数据去执行函数,更新视图。

  • new MVVM()中存放这一些数据,有各个属性;

  • Observe(观察者1)用来劫持监听所有属性,一旦发现里面的数据发生变化了,订阅器(Dep)就会被通知数据发生变化,然后通知watcher数据发生变化了,让watcher去更新视图。

    • setter:设置值的时候触发
    • getter:获取值的时候触发
  • watcher(观察者2)

    • 更新视图ui
    • 添加观察者到订阅器(Dep)
  • Dep(订阅器)订阅是管理观察的一个实例对象

    • 通知属性发生变化的观察者,去更新视图。
    • 有多少个被观察的数据对象,就得创建多少个观察者,并放到订阅器Dep中(Dep相当于一个容器)
  • Compile(编译器):解析指令