昨天被導師叫去研究了一下vue的雙向數據綁定原理。。。原本覺得原理的東西都很是高深,沒想到vue的雙向綁定真的很好理解啊。。。本身動手寫了一個。javascript
傳送門html
雙向綁定的思想前端
雙向數據綁定的思想就是數據層與UI層的同步,數據再二者之間的任一者發生變化時都會同步更新到另外一者。vue
雙向綁定的一些方法java
目前,前端實現數據雙向數據綁定的方法大體有如下三種:git
1.發佈者-訂閱者模式(backbone.js)github
思路:使用自定義的data屬性在HTML代碼中指明綁定。全部綁定起來的JavaScript對象以及DOM元素都將「訂閱」一個發佈者對象。任什麼時候候若是JavaScript對象或者一個HTML輸入字段被偵測到發生了變化,咱們將代理事件到發佈者-訂閱者模式,這會反過來將變化廣播並傳播到全部綁定的對象和元素。數組
2.贓值檢測(angular.js)瀏覽器
思路:經過輪詢的方式檢測數據變更。才特定的事件觸發時進入贓值檢測。app
大體以下:
• 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>