完整高頻題庫倉庫地址:https://github.com/hzfe/awesome-interview
完整高頻題庫閱讀地址:https://hzfe.github.io/awesome-interview/
相關(guān)問題
- computed 和 watch 的實(shí)現(xiàn)原理
- computed 和 watch 的適用場(chǎng)景
回答關(guān)鍵點(diǎn)
響應(yīng)變化
屬性
偵聽
computed 是模板表達(dá)式的聲明式描述,會(huì)創(chuàng)建新的響應(yīng)式數(shù)據(jù)啦撮。而 watch 是響應(yīng)式數(shù)據(jù)的自定義偵聽器,用于響應(yīng)數(shù)據(jù)的變化。除此之外,computed 還具有可緩存慕购,可依賴多個(gè)屬性邻邮,getter 函數(shù)無副作用等特點(diǎn)。watch 則更適用于異步或開銷大的操作鹊杖。
知識(shí)點(diǎn)深入
1. 實(shí)現(xiàn)原理
在了解 Vue 數(shù)據(jù)雙向綁定的基礎(chǔ)上,computed 等同于為屬性設(shè)置 getter 函數(shù)(也可設(shè)置 setter)扛芽,而 watch 等同于為屬性的 setter 設(shè)置回調(diào)函數(shù)骂蓖、監(jiān)聽深度 deep 及響應(yīng)速度 immediate。下面簡(jiǎn)單講解下兩者的實(shí)現(xiàn)原理川尖,具體細(xì)節(jié)可以參考源碼登下。
1.1 computed 原理
主要分為四個(gè)階段
- 初始化:為 computed 屬性創(chuàng)建 lazy watcher(此處 watcher 指雙向綁定中的監(jiān)聽器,下同)叮喳。
- 首次模板渲染:渲染 watcher 檢測(cè)到 computed 屬性時(shí)被芳,會(huì)調(diào)用 computed 屬性的 getter 方法,而 computed 屬性的 getter 方法會(huì)調(diào)用依賴屬性的 getter馍悟,從而形成鏈?zhǔn)秸{(diào)用畔濒,同時(shí)保存引用關(guān)系用于更新。取得計(jì)算結(jié)果后 lazy watcher 會(huì)將結(jié)果緩存锣咒,并返回給渲染 watcher 進(jìn)行模板渲染侵状。
- 多次模板渲染:直接取 lazy watcher 中的緩存值給到渲染 watcher 進(jìn)行渲染。
- 依賴屬性更新:根據(jù)首次模板渲染階段構(gòu)建的依賴關(guān)系向上通知 lazy watcher 進(jìn)行重新計(jì)算毅整,緩存計(jì)算結(jié)果并通知渲染 watcher 重新渲染更新頁面趣兄。
1.2 watch 原理
watch 本質(zhì)上是為每個(gè)監(jiān)聽屬性 setter 創(chuàng)建了一個(gè) watcher,當(dāng)被監(jiān)聽的屬性更新時(shí)悼嫉,調(diào)用傳入的回調(diào)函數(shù)诽俯。常見的配置選項(xiàng)有 deep 和 immediate,對(duì)應(yīng)原理如下:
- deep:深度監(jiān)聽對(duì)象承粤,為對(duì)象的每一個(gè)屬性創(chuàng)建一個(gè) watcher暴区,從而確保對(duì)象的每一個(gè)屬性更新時(shí)都會(huì)觸發(fā)傳入的回調(diào)函數(shù)。主要原因在于對(duì)象屬于引用類型辛臊,單個(gè)屬性的更新并不會(huì)觸發(fā)對(duì)象 setter仙粱,因此引入 deep 能夠很好地解決監(jiān)聽對(duì)象的問題。同時(shí)也會(huì)引入判斷機(jī)制彻舰,確保在多個(gè)屬性更新時(shí)回調(diào)函數(shù)僅觸發(fā)一次伐割,避免性能浪費(fèi)候味。
- immediate:在初始化時(shí)直接調(diào)用回調(diào)函數(shù),可以通過在 created 階段手動(dòng)調(diào)用回調(diào)函數(shù)實(shí)現(xiàn)相同的效果隔心。
2. 適用場(chǎng)景
- computed:需要處理復(fù)雜邏輯的模板表達(dá)式白群。
- watch:需要執(zhí)行異步或開銷較大的操作。
從表現(xiàn)上看硬霍,computed 會(huì)創(chuàng)建新的屬性帜慢,而 watch 可以通過將屬性設(shè)置在 data 中,再監(jiān)聽依賴屬性變化唯卖,調(diào)用 handler 方法更新屬性的方式達(dá)到同樣的效果粱玲。因此不難得出 computed 的使用場(chǎng)景可以被 watch 覆蓋這一結(jié)論。但在具體的使用上還是優(yōu)先考慮 computed拜轨,因?yàn)橄嗤瑘?chǎng)景下 watch 所需的代碼量和性能開銷一般來說會(huì)比 computed 大抽减,具體可以參照 computed vs watched。在 computed 無法滿足需求的情況下再考慮使用 watch橄碾,也可以有效避免 watch 濫用卵沉,提升性能。
3. Vue3 與 Vue2 區(qū)別
Vue3 中 computed 和 watch 的原理以及在 Options API 中的使用方式和 Vue2 保持一致法牲。但在 Vue3 的新特性組合式(Composition)API 中偎箫,使用方式和功能相比 Vue2 有了明顯差別。使用方式由原來在組件中聲明改為直接從 Vue 中導(dǎo)入使用皆串,各自的調(diào)用方式和參數(shù)也發(fā)生了改變,功能更加多樣眉枕,同時(shí) Vue3 還引入了 watchEffect 作為 watch 的補(bǔ)充恶复,以求用更簡(jiǎn)潔的代碼來覆蓋更廣的使用場(chǎng)景。具體使用參考官方文檔速挑。
參考資料
2. Vuejs 源碼
3. Vue3 組合式 api