一、偵聽屬性watch:
1、不支持緩存,當(dāng)數(shù)據(jù)變化時,會直接觸發(fā)對應(yīng)的操作。
2、watch支持異步
3、監(jiān)聽函數(shù)接收兩個參數(shù),第一個新值,第二個舊值。
4、當(dāng)一個屬性發(fā)生變化時,需要執(zhí)行對應(yīng)的操作,一對多;
5、監(jiān)聽數(shù)據(jù)必須是data中聲明過或者父組件傳遞過來的props中的數(shù)據(jù),當(dāng)數(shù)據(jù)變化時,觸發(fā)對應(yīng)的操作.
函數(shù)有兩個參數(shù): immediate:組件加載立即觸發(fā)回調(diào)函數(shù)執(zhí)行;
deep:深度監(jiān)聽,為了發(fā)現(xiàn)對象內(nèi)部值的變化,復(fù)雜類型的數(shù)據(jù)使用,例如數(shù)組中的對象內(nèi)容的改變,注意監(jiān)聽數(shù)組的變化不需要這么做。
注意:deep無法監(jiān)聽到數(shù)組的變動和對象的新增,參考vue數(shù)組變異,只有以響應(yīng)式的方式觸發(fā)才會被監(jiān)聽到。
6、當(dāng)需要在數(shù)據(jù)變化時執(zhí)行異步或者開銷較大的操作時,使用watch是最佳的。

二、計算屬性computed:
1、支持緩存,只有依賴數(shù)據(jù)發(fā)生變化時,才會重新進(jìn)行計算
2、不支持異步,當(dāng)computed內(nèi)有異步操作時無效,無法監(jiān)聽數(shù)據(jù)變化
3、computed屬性值默認(rèn)會走緩存,計算屬性是基于他們的響應(yīng)式依賴進(jìn)行緩存的,也就是基于data中聲明過或者父組件傳遞的props中的數(shù)據(jù)通過計算得到的值。
4、如果一個屬性是由其他屬性計算而來的,這個屬性依賴其他屬性,是一對一或者多對一,一般用computed。

6、如何實現(xiàn)緩存,其實就是使用dirty標(biāo)志位來標(biāo)識數(shù)據(jù)有沒有更新,
在計算屬性初始化時,會將computed對象中的每一個key創(chuàng)建一個watcher,當(dāng)值發(fā)生變化的時候,會調(diào)用update方法將dirty置為true,當(dāng)每次取值時會根據(jù)dirty來判斷是重新計算還是直接讀取值,如果dirty為true,調(diào)用evaluate函數(shù)重新計算,將dirty置為false;如果dirty為false,直接讀取值.
Object.defineProperty(target, key, {
get() {
// 從剛剛說過的組件實例上拿到 computed watcher
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
// 條件成立說明值更新過,需要重新計算
if (watcher.dirty) {
// 這里會求值 調(diào)用 get
watcher.evaluate()
}
if (Dep.target) {
watcher.depend()
}
// 最后返回計算出來的值
return watcher.value
}
}
evaluate () {
// 調(diào)用 get 函數(shù)求值
this.value = this.get()
// 把 dirty 標(biāo)記為 false
this.dirty = false
}
update () {
if (this.lazy) {
this.dirty = true
}
}