Vue:實現雙向數據綁定

參考

剖析Vue原理&實現雙向綁定MVVM
javascript實現數據雙向綁定的三種方式

Vue實現雙向數據綁定的方式

Vue是如何實現雙向數據綁定的呢?答案是前端數據劫持。其通過Object.defineProperty()方法,這個方法可以設置gettersetter函數,在setter函數中,就可以監聽到數據的變化,從而更新綁定的元素的值。

實現對象屬性變化綁定到UI

大概的思路是:
1. 確定綁定的數據,使用Object.defineProperty()對其數據變化進行監聽(對應defineGetAndSet)
2. 一旦數據發生改動,會觸發setter函數。因此在setter函數內要調用回調函數觸發綁定元素的更新。
3. 綁定元素的更新就是遍歷所有的綁定元素,通過綁定屬性的值確定函數的調用,並傳入修改後的值。(對應scan)

實現UI變化綁定到對象屬性

這個就比較簡單了,因爲UI的改變會觸發一些事件,比如keyup。通過監聽事件來實現數據的改變。而上面說了,數據的改變又會導致綁定其值的元素的UI改變。

實現

var data = {
  value: 'hello world!'
}
var bindValue;
//確定綁定的元素
var bindelems = [document.getElementById('p'), document.getElementById('input')];
//修改綁定元素的值的方法
var command = {
  text: function(str) {
    this.innerHTML = str;
  },
  value: function(str) {
    this.value = str;
  }
};
//遍歷綁定元素修改其值
var scan = function() {
  console.log('in scan');
  for(var i = 0; i < bindelems.length; i++) {
    var elem = bindelems[i];
    console.log('elem',elem);
    for(var j = 0; j < elem.attributes.length; j++) {
      var attr = elem.attributes[j];
      if(attr.nodeName.indexOf('q-')>=0) {
        command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
      }
    }
  }
}
//設置劫持
var defineGetAndSet = function(obj, propname) {
  Object.defineProperty(obj, propname, {
    get: function() {
      return bindValue;
    },
    set: function(value){
      bindValue = value;
      scan();
    },
    enumerable: true,
    configurable: true
  })
} 
//一開始先初始化,使所有綁定的元素值爲初始值
scan();
//設置需要被劫持的元素
defineGetAndSet(data, 'value');
//監聽UI變化
bindelems[1].addEventListener('keyup', function(e) {
  data.value = e.target.value;
});
setTimeout(function() {
  data.value = 'change';
}, 1000);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章