JS實現雙向綁定

       如今前端MVVM思想盛行,經過對數據的改變從而引發頁面的變化,如:Vue中實現雙向綁定的原理就是:採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的settergetter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調,Object.defineProperty()就是本文所要講的一個東西html

Object.defineProperty( obj, propName, desc)

obj:要監聽屬性所在的對象前端

propName:要監聽屬性的名字瀏覽器

desc:描述符對象bash

         a、configurable:Booleans  表示可否經過delete刪除屬性從而從新定義屬性,默認爲true函數

         b、enumerable:Booleans   表示可否經過for-in循環返回屬性,默認值爲trueui

         c、writable:Booleans   表示可否修改屬性的值,默認值爲truethis

         d、value:包含這個屬性的數據值,讀取屬性值的時候從這個位置讀,寫入屬性值的時候把新值保存在這個位置,默認值爲undefinedspa

好比咱們經常使用的對象賦值操做let person = { name: 'Jone' },用Object.defineProperty()實現以下:scala

let person = {};
Object.defineProrerty( person, 'name', {
    writable: false,    //設置爲只讀,不可改寫
    value: 'Jone'       //設置屬性值
}
console.log(person.name);    //'Jone'
person.name = 'Bob';
console.log(person.name);    //'Jons'複製代碼

上面的例子中,咱們爲person這個對象增長了一個name的屬性,而且給該屬性賦值,且把該屬性設置爲只讀,若是從新給該屬性賦值,在非嚴格模式下,賦值操做將被忽略,在嚴格模式下則會報錯,另外三個configurable、enumerable這兩個屬性也一樣能夠像如上設置,在此就不一一列舉,你們能夠自行嘗試雙向綁定

注:IE8是第一個實現Object.defineProperty( )方法的瀏覽器版本,然而這個版本的實現存在諸多限制:只能在DOM對象上使用這個方法,並且只能建立訪問器屬性,實現不完全,這也是爲何Vue不兼容IE8的一個重要緣由

       Object.defineProperty( )內還包含一對兒gettersetter函數,它們被稱做這個對象的訪問器屬性,這兩個函數都不是必須的,只是在讀取訪問對象屬性時,會調用getter函數,這個函數負責返回有效值,在寫入對象屬性時,會調用setter函數並傳入新值,這個函數負責決定如何處理數據,請看下面例子:

let obj = {};
Object.defineProperty(obj, 'age', {
  set: function ( value ){
    console.log("正在寫值...");
    this.age = value;
  },
  get: function (){
    console.log("正在取值...");
    return this.age
  }
});
obj.age = '20';       //控制檯輸出:正在寫值,說明set函數被調用
let temp = obj.age;   //控制檯輸出:正在取值,說明get函數被調用複製代碼

經過上面的例子咱們能夠知道,當一個對象中的屬性被讀取,或者更改寫入的時候,經過Object.defineProperty( )這個函數中的set,和get,訪問器均可以攔截到對應的操做,這就是雙向綁定的關鍵所在,利用這一特性,便可實現簡單的雙向綁定效果,以下代碼:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>原生JS實現雙向綁定原理</title>
</head>
<body>
<div>
  <div style="margin-bottom: 20px">
    輸入框:<input id="input" type="text">
  </div>
  <div>
    展現框:<span id="show"></span>
  </div>
</div>
<script>
  let model = {};
  let inputObj = document.getElementById('input');
  let showObj = document.getElementById('show');
  Object.defineProperty(model, 'user', {
    set: function ( value ){
      this.user = value;
      showObj.innerText = value;
    },
    get: function (){
      return this.user;
    }
  });
  inputObj.addEventListener('keyup', function (){
    model[ 'user' ] = inputObj.value;
  });
</script>
</body>
</html>複製代碼

       代碼其實很簡單,明白了實現原理,你們能夠發揮本身的想象把它更加利用起來,我這裏只是一個拋磚引玉的效果

相關文章
相關標籤/搜索