Angular React Vue 比較 – 組件篇之生命周期

三大框架中實例化組件并渲染組件視圖時,組件實例的生命周期就開始了。生命周期一直伴隨著變更檢測,框架會檢查數(shù)據(jù)綁定屬性何時發(fā)生變化,并按需更新視圖和組件實例。當從應用中銷毀組件實例并從 DOM 中移除它渲染的模板時,生命周期就結(jié)束了。

我們的應用可以使用生命周期鉤子方法來觸發(fā)組件生命周期中的關鍵事件,以初始化新實例,需要時啟動變更檢測,在變更檢測過程中響應更新,并在刪除實例之前進行清理。

三大框架關于組件生命周期鉤子各不相同,但是對于我們來說最常用到的是掛載、更新和卸載這幾個鉤子,本章將對這三個鉤子來做比較。

Angular 組件生命周期鉤子

在這里,我們先列出 Angular 組件生命周期中的鉤子,下表中的關于鉤子的次序就是組件在生命周期中的執(zhí)行順序。

鉤子方法 用途 時機
ngOnChanges 當 Angular 設置或重新設置數(shù)據(jù)綁定的輸入屬性時響應。該方法接受當前和上一屬性值的對象。 如果組件綁定過輸入屬性,那么在 ngOnInit() 之前以及所綁定的一個或多個輸入屬性的值發(fā)生變化時都會調(diào)用。
ngOnInit 在 Angular 第一次顯示數(shù)據(jù)綁定和設置組件的輸入屬性之后,初始化組件。 在第一輪 ngOnChanges() 完成之后調(diào)用,只調(diào)用一次。而且即使沒有調(diào)用過 ngOnChanges(),也仍然會調(diào)用 ngOnInit()(比如當模板中沒有綁定任何輸入屬性時)。
ngDoCheck 檢測,并在發(fā)生 Angular 無法或不愿意自己檢測的變化時作出反應。 緊跟在每次執(zhí)行變更檢測時的 ngOnChanges() 和 首次執(zhí)行變更檢測時的 ngOnInit() 后調(diào)用。
ngAfterContentInit 當 Angular 把外部內(nèi)容投影進組件視圖或指令所在的視圖之后調(diào)用。 第一次 ngDoCheck() 之后調(diào)用,只調(diào)用一次。
ngAfterContentChecked 每當 Angular 檢查完被投影到組件中的內(nèi)容之后調(diào)用。 ngAfterContentInit() 和每次 ngDoCheck() 之后調(diào)用。
ngAfterViewInit 當 Angular 初始化完組件視圖及其子視圖調(diào)用。 第一次 ngAfterContentChecked() 之后調(diào)用,只調(diào)用一次。
ngAfterViewChecked 每當 Angular 做完組件視圖和子視圖或包含該指令的視圖的變更檢測之后調(diào)用。 ngAfterViewInit() 和每次 ngAfterContentChecked() 之后調(diào)用。
ngOnDestroy 每當 Angular 每次銷毀組件后調(diào)用并清掃。在這兒取消訂閱可觀察對象和事件綁定,以防內(nèi)存泄漏。 在 Angular 銷毀指令或組件后立即調(diào)用。

在 Angular 的組件生命周期中并沒有稱之為掛載、更新和卸載的鉤子,為了更方便的在三個框架中做對比,我們把它生命周期中類似于這幾個功能的鉤子稱之為掛載、更新和卸載。

掛載鉤子

ngAfterViewInit 鉤子會在完全初始化了組件的視圖后調(diào)用,它只會調(diào)用一次。這個鉤子中沒有參數(shù)。

更新鉤子

ngOnChanges 鉤子會在組件的輸入屬性發(fā)生了變化時調(diào)用,它會在組件初始化之前先調(diào)用一次。ngOnChanges() 方法獲取了一個對象,它把每個發(fā)生變化的屬性名都映射到了一個 SimpleChange 對象,該對象中有屬性的當前值和前一個值。這個鉤子會在這些發(fā)生了變化的屬性上進行迭代,并記錄它們。

如果組件并沒有綁定任何輸入屬性,那么此鉤子不會被調(diào)用。

需要注意的是在 Angular 組件的生命周期中并沒有組件自身屬性變化后可調(diào)用的鉤子,如果要監(jiān)測組件自身屬性的變化,可以使用 RxJS 庫來創(chuàng)建和訂閱可觀察的對象。

卸載鉤子

ngOnDestroy 鉤子會在組件實例被銷毀后調(diào)用,這個鉤子中沒有參數(shù)。

React 組件生命周期鉤子

和其他兩個框架不一樣,在 React 的函數(shù)式組件中并沒有可調(diào)用的生命周期鉤子。想要實現(xiàn)類似掛載、更新和卸載功能的鉤子可以使用 useEffect 鉤子。

需要注意的是,在編寫和讀取 Effect 時,要獨立地考慮每個 Effect(如何開始和停止同步),而不是從組件的角度思考(如何掛載、更新或卸載)。在本章中是為了與其他兩個框架做比較,才從組件的角度來使用 Effect 的。

在這里我們提供一段使用 useEffct 來實現(xiàn)上述三個鉤了的示例。

import { useState, useEffect } from 'react';

export default function Clock({ time }) {
  const [index, setIndex] = useState(0);

  useEffect(() => {
    // 【更新鉤子】當props與state變更、組件渲染后執(zhí)行
  });

  useEffect(() => {
    // 【掛載鉤子】組件渲染后僅執(zhí)行一次
    
    return () => {
      // 【卸載鉤子】組件在卸載后執(zhí)行
    }
  }, []);

  useEffect(() => {
    // 【更新鉤子】僅在index變更,組件渲染后執(zhí)行
  }, [index]);

  function handleClick() {
    setIndex(index + 1);
  }

  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <p>{index}</p>
      <div>{time}</div>
    <>
  );
}

掛載鉤子

使用 useEffect 鉤子,第二個參數(shù)傳遞 [] 時,會在組件渲染后僅調(diào)用一次這個鉤子。

useEffect(() => {
    // 【掛載鉤子】組件渲染后僅執(zhí)行一次
}, []);

更新鉤子

使用 useEffect 鉤子,不傳遞第二個參數(shù)時,會在 props 或 state 發(fā)生變更、組件渲染后調(diào)用這個鉤子。

useEffect(() => {
    // 【更新鉤子】當props與state變更、組件渲染后執(zhí)行
});

卸載鉤子

在 useEffect 鉤子中添加返回的函數(shù)會在組件被卸載后執(zhí)行。

useEffect(() => {
    // 【卸載鉤子】組件在卸載后執(zhí)行
});

Vue組件生命周期鉤子

在這里,我們先列出 Vue 組件生命周期中的鉤子,下表中的關于鉤子的次序就是組件在生命周期中的執(zhí)行順序。這些鉤子都應該在組件的 setup() 階段被同步調(diào)用。

鉤子方法 用途 時機
onBeforeMount 當這個鉤子被調(diào)用時,組件已經(jīng)完成了其響應式狀態(tài)的設置,但還沒有創(chuàng)建 DOM 節(jié)點。它即將首次執(zhí)行 DOM 渲染過程。 在組件被掛載之前被調(diào)用。
onMounted 這個鉤子通常用于執(zhí)行需要訪問組件所渲染的 DOM 樹相關的副作用。 在組件掛載完成后執(zhí)行。
onBeforeUpdate 這個鉤子可以用來在 Vue 更新 DOM 之前訪問 DOM 狀態(tài)。在這個鉤子中更改狀態(tài)也是安全的。 在組件即將因為響應式狀態(tài)變更而更新其 DOM 樹之前調(diào)用。
onUpdated 這個鉤子會在組件的任意 DOM 更新后被調(diào)用,這些更新可能是由不同的狀態(tài)變更導致的,因為多個狀態(tài)變更可以在同一個渲染周期中批量執(zhí)行(考慮到性能因素)。 在組件因為響應式狀態(tài)變更而更新其 DOM 樹之后調(diào)用。
onBeforeUnmount 當這個鉤子被調(diào)用時,組件實例依然還保有全部的功能。 在組件實例被卸載之前調(diào)用。
onUnmounted 可以在這個鉤子中手動清理一些副作用,例如計時器、DOM 事件監(jiān)聽器或者與服務器的連接。 在組件實例被卸載之后調(diào)用。

掛載鉤子

onMounted 鉤子在組件掛載完成后調(diào)用,它只會執(zhí)行一次。

更新鉤子

onUpdated 鉤子在組件因為響應式狀態(tài)變更而更新其 DOM 樹之后調(diào)用。

卸載鉤子

onUnmounted 鉤子在組件實例被卸載之后調(diào)用。

小結(jié)

本章介紹了三大框架組件的生命周期中的鉤子,對掛載、更新與卸載鉤子做了重點說明。

Angular 中是類組件,實例化的組件可以理解成一個類的對象,把組件實例生命周期的鉤子當成對象的方法考慮會更好理解。

React 函數(shù)組件中并沒有可以調(diào)用的生命周期鉤子,在編寫和讀取 Effect 時,要獨立地考慮每個 Effect(如何開始和停止同步),而不是從組件的角度思考(如何掛載、更新或卸載)。

Vue 組件生命周期中關于掛載、更新和卸載的鉤子符合我們的直觀描述,更好理解一些。

文章參考鏈接:

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容