Vue之watch一個computed變量時,computed所依賴的變量值被改變會怎樣?


vm.init,先為computed變量(假設是age,並在computed方法中依賴於另一個變量vm.factor)初始化,age會關聯一個watcher(假設為cWatcher,lazy為true),vm.age的get方法被重寫,cWatcher的dirty屬性被置為true。其getter屬性指向的是computed中定義的age的get方法,其cb屬性指向的是noop。

接下來initWatch,再new 一個Watcher(假設叫wWatcherlazy為false),其getter屬性指向的方法實際上調用的是vm.age的get方法(被重寫之后的那個),其cb屬性指向的是options對象里watch中age的hander方法。因為wWatcher的lazy屬性為false,那么在構造方法中會直接調用wWatcher的get方法,邏輯是把當前wWatcher放到Dep的棧頂,調用getter方法,也就是vm.age的get方法,發現cWatcher.dirty為true(注意這里由wWatcher變成了cWatcher),調用cWatcher的get方法,發現cWatcher的dirty為true,那么調用cWatcher的evaluate方法,this.value=get()中,把cWatcher入棧,調用vm.age的get方法計算age的值,此時例如vm.factor在initComputed之前調用過initData的,所以factor的get方法中,會調用defineReactive方法閉包中的Dep,收集cWatcher(同時cWatcher也會收集這些Dep),那么以后factor的set方法被執行設置成另一個值的時候,會調用cWatcher的update方法。從cWatcher的evaluate方法中出來,有if(Dep.target).....的方法,注意此時的Dep.target是wWatcher了,這時候cWatcher的depend方法,會讓cWatcher剛才調用vm.age收集到的Dep,例如factor的那個閉包中的Dep,和wWatcher相互收集。那么此時factor的Dep中既收集到了cWatcher,又收集到了wWatcher。

如果接下來,改變factor為另一個值。那么會先后調用cWatcher和wWatcher的update方法,先說前者,因為是lazy的,所以僅僅把dirty設置為true。接下來調用wWatcher的update,把它的run方法放到微任務隊列中執行,先執行wWatcher的get方法,調用vm.age的被重寫的get方法,獲取value,此時如果factor的改變導致age的值改變了,那么這個value和wWatcher中保存的value不同,回往下執行wWatcher的cb也就是options對象里watch中age的hander方法,這個也是合理的。但是如果factor的改變並沒有導致age的值改變,將不會調用cb。

綜上所述,之所以computed的變量的watch會變得比普通變量的watch復雜的多,這是因為普通變量的Dep存在與defineReactive方法的閉包中,get方法收集watcher,set方法響應。而computed的變量並沒有這個Dep和閉包,只有借助它依賴的變量進行對cWatcher和wWatcher的收集和響應。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM