zoukankan      html  css  js  c++  java
  • 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()方法。

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

    完整demo戳这里!  

      

     

  • 相关阅读:
    [luogu4053 JSOI2007] 建筑抢修 (贪心 优先队列)
    [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)
    20180705 考试记录
    [luogu4310] 绝世好题 (递推)
    [luogu2765 网络流24题] 魔术球问题 (dinic最大流)
    [luogu4151 WC2011] 最大XOR和路径 (线性基)
    [luogu3232 HNOI2013] 游走 (高斯消元 期望)
    [luogu3726 HNOI2017] 抛硬币 (拓展lucas)
    20180703 考试记录
    [spoj] HIGH
  • 原文地址:https://www.cnblogs.com/LuckyWinty/p/6102913.html
Copyright © 2011-2022 走看看