不過目前可以說一句,watch與vue底層監視,用的是一套類似的邏輯
這個概念是非常重要的,所以這節課是不能跳過的,否則有一天會為這個行為買單(謝謝,已經買過了)
我們先來做個需求吧,這個需求不演示不行
這是我的html設計,ul 當中的li標籤渲染data當中persons這個陣列的資料
button按鈕呢,設定了一個點選事件,這個點選事件用來單獨修改 馬冬梅這個物件的資訊
可以看到,在這種賦值的情況下,我們成功的對 馬冬梅 進行了修改資料
並且在vue當中也能檢測到
既然是 對馬冬梅進行修改,我們換一種方式來對他進行修改
為什麼這次資料修改不成功了,這是為什麼?
我們雖然新增的是age,但是這裡的意思是將原有屬性age覆蓋掉,使用這個新的age
我們來看下測試結果
所以,vue底層的資料代理,或者說資料加工沒有我們想的這麼簡單,那麼人家是怎麼實現的呢
1、首先我們準備一個data,這裡面存放了兩個屬性,name和age
2、我們建立一個function ==> Observer
然後範例化這個 Observer,js當中,function是可以當做建構函式使用的
該函數需要一個屬性,從引數名可以看出,這是一個物件屬性
3、現在我們就來設定這個物件,首先我們需要獲取到 data這個物件當中的所有key值
4、對這個陣列,進行迴圈
5、在迭代的過程當中,使用definedProperty進行資料代理
引數解析,為什麼這裡,新增資料的物件(引數1) 是 this?
6、get和set
陣列當中是可以用字串來獲取元素值的(很少)
完整程式碼
// 這有一個物件,物件有兩個屬性
let data = {
name: "waves",
age: 0
}
// 範例化一個監視器物件
let observer = new Observer(data);
// 監視物件Observer
function Observer(obj){
// 1、獲取data當中的所有key值
let properties = Object.keys(data); // ["name","age"]
// 2、迭代 properties陣列
properties.forEach((property)=>{
// 3、在迭代的過程當中,使用definedProperty進行資料代理
Object.defineProperty(this,property,{
// 設定get和set
get(){
// 很簡單,因為data沒有做資料代理,返回data[property]即可
return data[property]; // data["name"] = waves
},
set(val){
// 賦值即可
data[property] = val
}
})
})
}
vue在這裡寫了遞迴,一直找,找到這個屬性不再是物件為止
陣列也是一個道理,vue也能給你找出來,不過 關於陣列和物件的代理,這二者的處理方式不同,下節會講解