欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue双向数据绑定原理探究(附demo)

程序员文章站 2022-05-14 07:54:06
昨天被导师叫去研究了一下vue的双向数据绑定原理。。。本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊。。。自己动手写了一个。 传送门 双向绑定的思想...

昨天被导师叫去研究了一下vue的双向数据绑定原理。。。本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊。。。自己动手写了一个。

传送门

双向绑定的思想

双向数据绑定的思想就是数据层与ui层的同步,数据再两者之间的任一者发生变化时都会同步更新到另一者。

双向绑定的一些方法

目前,前端实现数据双向数据绑定的方法大致有以下三种:

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

思路:使用自定义的data属性在html代码中指明绑定。所有绑定起来的javascript对象以及dom元素都将“订阅”一个发布者对象。任何时候如果javascript对象或者一个html输入字段被侦测到发生了变化,我们将代理事件到发布者-订阅者模式,这会反过来将变化广播并传播到所有绑定的对象和元素。

2.赃值检测(angular.js)

思路:通过轮询的方式检测数据变动。才特定的事件触发时进入赃值检测。

大致如下:

•   dom事件,譬如用户输入文本,点击按钮等。( ng-click )

•   xhr响应事件 ( $http )

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

•   timer事件( $timeout , $interval )

•   执行 $digest() 或 $apply()

3.数据劫持(vue.js)

思路:使用object.defineproperty对数据对象做属性get和set的监听,当有数据读取和赋值操作时则调用节点的指令,这样使用最通用的=等号赋值就可以触发了。

wue双向数据绑定小demo思路

①  构造一个wue对象,定义该对象的属性el、data,创建对象的时候传相应数据,并执行init()方法。

var wue=function(params){
 this.el=document.queryselector(params.el);
 this.data=params.data;
 this.init();
};

②  init方法中执行bindtext和bindmodel方法,这两个方法分别是解析dom中绑定了w-model、w-text指令的html,并作相应处理。

init:function(){
  this.bindtext();
  this.bindmodel();
 }

③  bindtext方法,把带有w-text指令的元素放进一个数组中,如:w-text='demo',然后令其innerhtml的值等于传进来的data[demo]。

bindtext:function(){
  var textdoms=this.el.queryselectorall('[w-text]'),
  bindtext;
  for(var i=0;i<textdoms.length;i++){
  bindtext=textdoms[i].getattribute('w-text');
  textdoms[i].innerhtml=this.data[bindtext];
  }
 }

④  bindmodel方法,把带有w-model指令的元素(一般为form相关元素)放进一个数组中,如:w-model='demo',为每一个元素绑定keyup事件(兼容浏览器写法)。

bindmodel:function(){
 var modeldoms=this.el.queryselectorall('[w-model]'),
 bindmodel;
 var _that=this;
 for(var i=0;i<modeldoms.length;i++){
 bindmodel=modeldoms[i].getattribute('w-model');
 modeldoms[i].value=this.data[bindmodel]||'';
 //数据劫持
 this.defineobj(this.data,bindmodel);
 if(document.addeventlistener){
 modeldoms[i].addeventlistener('keyup',function(event) {
  console.log('test');
  e=event||window.event;
  _that.data[bindmodel]=e.target.value;
 },false);
 }else{
 modeldoms[i].attachevent('onkeyup',function(event){
  e=event||window.event;
  _that.data[bindmodel]=e.target.value; 
 },false);
 }
 } 
}

⑤  使用object.defineproperty,定义set和get方法,并在set方法中调用bindtext方法。这是利用了一旦w-model的值在input中被改变,会自动执行set方法,所以只有在这个方法中调用更新w-text的方法即可。

defineobj:function(obj,prop,value){
  var val=value||'';
  var _that=this;
  try{
  object.defineproperty(obj,prop,{
  get:function(){
  return val;
  },
  set:function(newval){
  val=newval;
  _that.bindtext();
  }
  })
 
  }catch (err){
  console.log('browser not support!')
  } 
 }

⑥使用

html:<br><h3>双向数据绑定demo</h3>
<div id="wrap">
 <input type="text" w-model='demo'>
 <h5 w-text='demo'></h5>
</div><br>js:
 <script src='../js/wue.js'></script>
 <script>
 new wue({
 el:'#wrap',
 data:{
  demo:'winty'
 }
 })
 </script> 

完整demo下载:https://github.com/luckywinty/two-way-data

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!