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戳這里!  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM