vue--響應式原理(2)
阿新 • • 發佈:2020-12-03
很久之前就想寫一點自己對 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
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); // 輸出coverguo3. 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感興趣的小夥伴可以動手去實現這樣一個簡單的資料繫結。 如果傳入引數物件是一個“比較深”的物件(也就是其屬性值也可能是物件),那該怎麼辦呢?考慮傳遞迴調函式。 在實際應用中,當特定資料發生改變的時候,我們是希望做一些特定的事情的,而不是每一次都只能打印出一些資訊。所以,我們如何支援傳入回撥函式的功能?