<h2>几种实现双向绑定的做法</h2>
发布者-订阅者模式(backbone.js): 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value)
,这里有篇文章讲的比较详细,有兴趣可点这里
这种方式现在毕竟太low了,我们更希望通过 vm.property = value
这种方式更新数据,同时自动更新视图,于是有了下面两种方式
脏治检测(angular.js): angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图。$watchList(所有的属性都是绑定的属性)里面的每一个属性都会被$watch监听,如果$watchList里面的数据改变,会记录下新值是多少
●当事件触发时,会执行一个$digest训话,$digest循环遍历$watchList里面的属性是否有被更改,遍历结束后,记录更改的属性
●$digest再去遍历$scope里面所有的属性,检查是否有更新属性,如果有,会再去遍历$watchList($watchList至少执行两次)
●直到没有数据都更新为止($digest最多执行10次)
脏治检测过程中,系统会自动调用$apply()
(有时也需要手抖调用$apply()强制刷新页面,在异步更改模型属性后,要自己去手动更新页面)
数据劫持(vue.js): vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
已经了解到vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()
来实现对属性的劫持,达到监听数据变动的目的,无疑这个方法是本文中最重要、最基础的内容之一,如果不熟悉defineProperty,猛戳这里整理了一下,要实现mvvm的双向绑定,就必须要实现以下几点:
1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图4、mvvm入口函数,整合以上三者