在 ES5中新增了不少新的API, 例如 新增了 Object.xxx相關的方法,其中有一個定義屬性相關的 Object.defineProperty 這個方法(還有Object.defineProperties)這個方法是 vue框架實現數據監聽的核心方法,它的定義如下:
Object.defineProperty([Object] obj, [String] propname, [Object] desp )
desp 中可以配置的項目  
<1> writable:  true/false 是否可寫
<2> configurable : true/false 是否可以配置,例如刪除該屬性
<3> enumerable: true/false 指的是是否可以使用 for in循環遍歷屬性
<4> value:  值  ,屬性的值
我們在寫vue項目的時候會在 data屬性中添加我們自己的屬性,這個屬性在vue中是響應式的,也就是它可以監聽到數據的變化,做出相應的改變(例如DOM操作)
我們自己利用 defineProperty給屬性生成setter和getter(也就是其他編程語言里的存取器),就可以達到監聽數據變化的目的
下面我們來自己實現一個數據監聽的小 demo
有如下的數據
  let vue = {   data: {    title: 'life style',    content: 'bike walk sleep...'   }  };已經提前聲明的 data屬性及其內部的屬性,我們的目標是監聽 data中,title和content的變化
如何做到呢? 屬性的個數是不確定的,所以我們可以使用 for in循環遍歷data對象的所有的屬性
  //如何監聽用戶自定義的 data中屬性的改變?  let data = vue.data;  for (let prop in data) {   data['__' + prop] = data[prop]; //存儲私有屬性   Object.defineProperty(data, prop, {    enumerable : true,    set: function (newVal) {     console.log('你正在修改'+prop + ' !...操作DOM...');     // 數據校驗     this['__' + prop] = newVal;    },    get: function () {     console.log('getter 獲取值 ...');     return this['__' + prop];    }   });  }遍歷data屬性的時候調用 defineProperty來給data對象的屬性添加set和get方法,
我們給data添加一個新的屬性 __xxx來保存我們之前的值,以便在 get方法中獲取原來的值
set方法 用于監聽這個屬性被重新賦值,
get方法用于獲取你想要的格式的值
此處需要注意的是 不要在 set和get中 使用this賦值或者取值,這樣會導致循環調用,出現問題!!!
另外 我們不要使用 var,而要使用 let ,因為var不是塊作用域, 會導致你最后訪問到的prop總是最后一個
定義好之后,我們可以修改 data中title和content屬性了,
當我們給 title賦值的時候回自動調用 set, 獲取值得時候自動調用get
測試代碼
  // 賦值操作會調用這個屬性的set方法, 類似于 set('aaa')  data.title = 'aaa';  // 獲取值操作會調用這個屬性的get方法  console.log(data.title);  data.content = 123;  // 此種動態屬性方式也會觸發 set / get  data['title'] = 123;  console.log(data['title']);結果(建議在最新版的chrome中操作):

對剛剛的遍歷方法還存在一些問題和說明:
1.data屬性的某個屬性可能還是對象,也就是存在多層級對象監聽的問題
此時可以使用遞歸函數遍歷data的屬性,進行相同操作
2. 通過 data.title = 1是實際上是調用了 set方法, 這個類似于 OC中的點語法
3. 要同時定義多個屬性,可以使用
Object.defineProperties([Object] obj, [Object] props);
需要注意的是, 本文只是介紹 defineProperty的基本使用,并非代表vue的代碼實現
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答