1. 程式人生 > 實用技巧 >vue--監聽物件變化

vue--監聽物件變化

思路 我們有兩個難點需要解決。 第一:當物件的某個屬性變化的時候,如何觸發自定義的回撥函式? 答案:ES5中新添加了一個方法:Object.defineProperty,通過這個方法,可以自定義getter和setter函式,從而在獲取物件屬性和設定物件屬性的時候能夠執行自定義的回撥函式。 第二:物件往往是一個深層次的結構,物件的某個屬性可能仍然是一個物件,這種情況怎麼處理? 比如說
let data = {
    user: {
        name: "zhangsan",
        age: "24"
    },
    address: {
        city: 
"beijing" } };
答案:遞迴演算法,也就是下面程式碼中的walk函式。如果物件的屬性仍然是一個物件的話,那麼繼續new一個Observer,直到到達最底層的屬性位置。 下面是實現的具體程式碼。 程式碼
// 觀察者建構函式
function Observer(data) {
    this.data = data;
    this.walk(data)
}

let p = Observer.prototype;

// 此函式用於深層次遍歷物件的各個屬性
// 採用的是遞迴的思路
// 因為我們要為物件的每一個屬性繫結getter和setter
p.walk = function
(obj) { let val; for (let key in obj) { // 這裡為什麼要用hasOwnProperty進行過濾呢? // 因為for...in 迴圈會把物件原型鏈上的所有可列舉屬性都迴圈出來 // 而我們想要的僅僅是這個物件本身擁有的屬性,所以要這麼做。 if (obj.hasOwnProperty(key)) { val = obj[key]; // 這裡進行判斷,如果還沒有遍歷到最底層,繼續new Observer if (typeof
val === 'object') { new Observer(val); } this.convert(key, val); } } }; p.convert = function (key, val) { Object.defineProperty(this.data, key, { enumerable: true, configurable: true, get: function () { console.log('你訪問了' + key); return val }, set: function (newVal) { console.log('你設定了' + key); console.log('新的' + key + ' = ' + newVal) if (newVal === val) return; val = newVal } }) }; let data = { user: { name: "zhangsan", age: "24" }, address: { city: "beijing" } }; let app = new Observer(data);
遺留問題 上面實現的程式碼還有很多問題。 比如:1.只監聽的物件的變化,沒有處理陣列的變化。    2.當你重新set的屬性是物件的話,那麼新set的物件裡面的屬性不能呼叫getter和setter。比如像下圖所示,重新設定的job屬性就不在帶有自定義的getter和setter了,不再提示“你訪問了job"這些字樣。