学过vue基础的都应该知道,通过v-model命令可以实现数据双向绑定,上代码:
1 <div id="app"> 2 <input type="text" v-model="word"> 3 <p>{{word}}</p> 4 <button v-on:click='sayHi'>change model</button> 5 </div> 6 7 <script> 8 var vm=new Vue({ 9 el:"#app", 10 data:{ 11 word:'Hello World' 12 }, 13 methods:{ 14 sayHi:function(){ 15 this.word="nihao" 16 } 17 } 18 19 }) 20 </script>
效果:
双向绑定就是在单向绑定的基础上给可输入元素(input、text等)添加change(input)事件,来动态修改model和view。
实现数据绑定的做法大致有如下几种:
- 发布者-订阅者模式(backbone.js)
- 脏值检查(angular.js)
- 数据劫持(vue.js)
发布者-订阅者模式(backbone.js):一般通过sub、pub的方式实现数据绑定的视图的数据监听,更新数据方式的通常做法是vm.set('property', value)
脏值检查:angular.js是通过脏值检查的方式对比数据是否有变更,来决定是否更新视图,最简单的方式是通过setInterval()定时轮询检查数据变动。angular只有在指定的事件触发时进入脏值检查。如下
- DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
-
XHR响应事件 ( $http )
-
浏览器Location变更事件 ( $location )
-
Timer事件( $timeout , $interval )
-
执行 $digest() 或 $apply()
数据劫持:vue是采用数据劫持再结合发布者-订阅者模式的方式。通过Object.defineProperty()(ES5中该方法用来修改属性默认的特性)来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据:
关键点在于data如何更新视图,因为view更新视图其实可以通过事件监听即可,比如input标签监听‘input’事件就可以了。所以重点应该在于当数据改变时,如何更新视图。
数据更新视图的重点在于如何知道数据变了,只要知道数据变了。如果知道数据变了,就是通过Object.defineProperty()对属性设置一个set函数,当数据改变就会触发这个函数,所以只需将一些需要更新的方法放在这里面就可以实现数据更新视图了。
总结
vue是通过数据劫持的方式来实现数据绑定的,其中最核心的是通过Object.defineProperty()方法来实现对属性的劫持,达到监听数据变动的目的。
要实现mvvm的双向绑定,就必须实现以下几点:
1、实现一个数据监听器的Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知监听者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图。
4、mvvm入口函数,整合以上三者
流程图如下:
那为什么要进行双向绑定呢?
js跟html之间会有一些交互,比如事件等,当交互变多了之后,代码会变得很杂乱。前端框架可以解决这一问题,可以把一些常用的操作通过框架里的功能进行交互。