5分钟摸探vue实现双向绑定原理

发布者: xiaozhimn

mvvm模式在引入到前端开发后,引起了很大的轰动,从此jquery没落了,kissy也没落了,很多操作dom的工具库,从此流失了大量的用户,2016年,Vue.js可谓是大放异彩,以迅雷不及掩耳之势赶React超Angular,用惯jQuery的我一下子被Vue开篇介绍的双向绑定给惊着了!一下子按捺不住好奇心,打算刨根究底,看看双向绑定到底是怎样实现的?

angular,vue,backbone同样支持双向绑定,但是他们的实现方式大相径庭。
订阅者模式-backbone

Model 到 View 的数据传递,可以在 View 中监听 Model 的 change 事件,每当 Model 更新,View 
中重新执行 render。而 ViewModel 的数据传递,可以监听 View 对应的 DOM 元素的各种事件,
在检测到 View 状态变更后,将变更的数据发送到 Model

脏检测-AngularJS

采用“脏值检测”的方式,数据发生变更后,对于所有的数据和视图的绑定关系进行一次检测,
识别是否有数据发生了改变,有变化进行处理,可能进一步引发其他数据的改变,所以这个
过程可能会循环几次,一直到不再有数据变化发生后,将变更的数据发送到视图,更新页
面展现。如果是手动对 ViewModel 的数据进行变更,为确保变更同步到视图,需要手动
触发一次“脏值检测”,也就是大家通常使用的 apply进行触发。

数据劫持-VueJS

采用 ES5 提供的 Object.defineProperty() 方法,监控对数据的操作,从而可以
自动触发状态树的同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定
的视图,而不是对所有的数据都执行一次检测。

将数据的变化更新到视图上:

<div> 
     <input type="text" id="desc"></div> 
</div>
var $data = {}; 
var data = {}; 
Object.defineProperty($data, "desc", { 
     get: function() { 
          return document.getElementById('desc').value;
     }, 
     set: function(desc) { 
          if(data["desc"] == desc) {//如果老数据和新数据一致不更新视图
              return;
          } else {
             data["desc"] = desc;
          }
          document.getElementById('desc').value = desc; //更新视图
     } 
}); 
$data.desc = "我是ue2,我来自西安,..."

将视图的变化更新到模型数据上

<div> 
     <input type="text" id="desc"></div> 
</div>
var $data = {};
var data = {}; 
Object.defineProperty($data, "desc", { 
     get: function() { 
          return document.getElementById('desc').value;
     }, 
     set: function(desc) { 
          data["desc"] = desc;
     } 
}); 
var viewEle = document.querySelector('#desc');
viewEle.onkeyup=function(){
     $data.desc = this.value;
}
vue底层对所有需要进行双向绑定的元素进行了事件监听。

通过以上的例子我们就实现了一个简单的双向绑定,从而可以简单的了解到vue底层的双向绑定原理了。
如果按照vue的双向绑定语法需要在input标签中添加v-model表达式,我们不难推测出,vue的
beforeCreated生命周期就是在做预编译过程,解析v-model标签将视图和数据模型进行关联,同时
为虚拟视图绑定事件,将两者进行双向绑定。

0赞

初次见面

SAS

时间:2/14/2019, 5:03:28 PM

回复