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

昨天被导师叫去研究了一下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()方法。

1
2
3
4
5
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,并作相应处理。

1
2
3
4
init: function (){
             this .bindText();
             this .bindModel();
        }

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

1
2
3
4
5
6
7
8
9
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事件(兼容浏览器写法)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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的方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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!' )
          
         }

⑥使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值