1. 程式人生 > 實用技巧 >vue--響應式原理(2)

vue--響應式原理(2)

很久之前就想寫一點自己對 Vue 的理解,雖然談不上深刻,但是畢竟對所用的東西有一點好奇,如果你跟我一樣,對 Vue 響應式原理有那麼一點好奇,那麼我們一起來研究一下吧。 在談 Vue 響應式原理之前,我們需要先了解一下 ES5 的 Object 的一個屬性 defineProperty。 下面我們來看一段官方的介紹 The Object.defineProperty() method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.
直接在一個物件上定義一個新的屬性,或修改一個已經存在的屬性。這個方法會返回該物件。 語法: Object.defineProperty(obj, prop, descriptor) 引數說明: @params obj // 目標物件 type: Obejct @params prop // 需要定義的屬性 type: String @params descriptor // 定義的屬性所擁有的特性 type: Obejct 通過簡單的介紹可以看看到,也就是定義了個物件的某個屬性,但是其中的奧祕主要在第三個引數 descriptor。 我們看一下第三個引數可以設定的屬性:
  • value
  • writable
  • get ,set
  • configurable
  • enumerable
分別介紹一下每個屬性: 1. value 屬性的值, 預設為undefined。例如:
var someOne = {}
Object.defineProperty(someOne, 'name', {
    value : 'cover'
})
someOne.name // cover
從表面上看, 貌似和下面的語法是等價的: someOne.name = 'cover' 那我們繼續往下看接下來的屬性。 2. writable 該屬性是否可寫, 如果設定成 false,則任何對該屬性改寫的操作都無效(但不會報錯),預設為 false。
var someOne = { };
Object.defineProperty(someOne, "name", {
    value:"coverguo" , // 由於設定了writable屬性為false 導致這個量不可以修改
    writable: false 
});  
console.log(someOne.name); // 輸出 coverguo
someOne.name = "monkeyWang";
console.log(someOne.name); // 輸出coverguo
3. configurable 如果為 false,則任何嘗試刪除目標屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無效化,預設為 false。
var someOne = { };
Object.defineProperty(someOne, "name", {
    configurable: false, // 由於設定了configurable屬性為false導致所有屬性不可修改
    value: "hello"
});  
// 下面的操作想讓 configurable 變為 true 但是不會被允許
Object.defineProperty(someOne, "name", {
    configurable: true,
    value: "hello"
});  // Cannot redefine property: name


var someOne = { };
Object.defineProperty(someOne, "name", {
   configurable: true, // 由於設定了configurable屬性為false導致所有屬性不可修改
    value: "hello"
});  
// 下面的操作想讓 configurable 變為 false 是可以的
Object.defineProperty(someOne, "name", {
   configurable: false,
    value: "hello"
});  
4. enumerable 是否能在for...in迴圈中遍歷出來或在Object.keys中列舉出來。預設為 false。
var someOne = {}
Object.defineProperty(someOne,"name",{
  value:3445,
  enumerable:true
})
console.log(Object.keys(someOne));// 列印["name"]

改為false

var someOne = {}
Object.defineProperty(someOne,"name",{
  value:3445,
  enumerable:false //注意咯這裡改了
})
console.log(Object.keys(someOne));// 列印[]
for...in 類似,不贅述了。 接下來看看更加關鍵的幾個屬性:set 和 get 5. set 和 get 在 descriptor 中不能同時設定訪問器(get 和 set)和 wriable 或 value,否則會錯,就是說想用 get 和 set,就不能用 writable 或 value 中的任何一個。 set 和 get,他倆幹啥用的的。
var someOne= {}
Object.defineProperty(someOne,"name",{
    set: function (newValue) {
      console.log('你設定了name,新的值是' + newValue);
    },
    get: function (value) {
      console.log('你訪問了name');
    }
})
someOne.name = 'monkeyWang'// 你設定了name,新值是monkeyWang
console.log(someOne.name)    // 你訪問了name
簡單來說,這個 “b” 賦值或者取值的時候會分別觸發 set 和 get 對應的函式。 演習: 瞭解了上面這麼多,那我們便可以開始 Vue 的基本響應式之旅了:我們從最簡單的開始。其中,動態資料繫結就是 Vue 最為基礎,最為有用的一個功能。這個系列將分成5部分,一步一步來理解和實現這一功能。ok,我們從最簡單的開始。給定任意一個物件,如何監聽其屬性的讀取與變化?也就是說,如何知道程式訪問了物件的哪個屬性,又改變了哪個屬性?
let app1 = new Observer({
  name: 'youngwind',
  age: 25
});

let app2 = new Observer({
  university: 'bupt',
  major: 'computer'
});

// 要實現的結果如下:
app1.data.name // 你訪問了 name
app.data.age = 100;  // 你設定了 age,新的值為100
app2.data.university // 你訪問了 university
app2.data.major = 'science'  // 你設定了 major,新的值為 science 
感興趣的小夥伴可以動手去實現這樣一個簡單的資料繫結。 如果傳入引數物件是一個“比較深”的物件(也就是其屬性值也可能是物件),那該怎麼辦呢?考慮傳遞迴調函式。 在實際應用中,當特定資料發生改變的時候,我們是希望做一些特定的事情的,而不是每一次都只能打印出一些資訊。所以,我們如何支援傳入回撥函式的功能?