將你的 UI 視為樹狀結構

你的 React 應用程式正在成形,許多元件彼此巢狀。 React 如何追蹤應用程式的元件結構?

React 和許多其他 UI 函式庫都將 UI 建模為樹狀結構。將你的應用程式視為樹狀結構有助於理解元件之間的關係。這種理解將幫助你除錯未來的概念,例如效能和狀態管理。

你將學到

  • React 如何「看待」元件結構
  • 什麼是渲染樹以及它的用途
  • 什麼是模組依賴樹以及它的用途

你的 UI 作為樹狀結構

樹狀結構是一種項目之間的關係模型,UI 通常使用樹狀結構來表示。例如,瀏覽器使用樹狀結構來建模 HTML (DOM) 和 CSS (CSSOM)。行動平台也使用樹狀結構來表示其視圖階層。

Diagram with three sections arranged horizontally. In the first section, there are three rectangles stacked vertically, with labels 'Component A', 'Component B', and 'Component C'. Transitioning to the next pane is an arrow with the React logo on top labeled 'React'. The middle section contains a tree of components, with the root labeled 'A' and two children labeled 'B' and 'C'. The next section is again transitioned using an arrow with the React logo on top labeled 'React DOM'. The third and final section is a wireframe of a browser, containing a tree of 8 nodes, which has only a subset highlighted (indicating the subtree from the middle section).
Diagram with three sections arranged horizontally. In the first section, there are three rectangles stacked vertically, with labels 'Component A', 'Component B', and 'Component C'. Transitioning to the next pane is an arrow with the React logo on top labeled 'React'. The middle section contains a tree of components, with the root labeled 'A' and two children labeled 'B' and 'C'. The next section is again transitioned using an arrow with the React logo on top labeled 'React DOM'. The third and final section is a wireframe of a browser, containing a tree of 8 nodes, which has only a subset highlighted (indicating the subtree from the middle section).

React 從你的元件建立 UI 樹。在此範例中,UI 樹狀結構會用於渲染到 DOM。

如同瀏覽器和行動平台,React 也使用樹狀結構來管理和建模 React 應用程式中元件之間的關係。這些樹狀結構是有用的工具,可以理解資料如何在 React 應用程式中流動,以及如何最佳化渲染和應用程式大小。

渲染樹

元件的主要特性是能夠組合其他元件的元件。當我們 巢狀元件 時,我們會有父元件和子元件的概念,其中每個父元件本身可能是另一個元件的子元件。

當我們渲染 React 應用程式時,我們可以在樹狀結構中建模這種關係,稱為渲染樹。

這是一個渲染勵志名言的 React 應用程式。

import FancyText from './FancyText';
import InspirationGenerator from './InspirationGenerator';
import Copyright from './Copyright';

export default function App() {
  return (
    <>
      <FancyText title text="Get Inspired App" />
      <InspirationGenerator>
        <Copyright year={2004} />
      </InspirationGenerator>
    </>
  );
}

Tree graph with five nodes. Each node represents a component. The root of the tree is App, with two arrows extending from it to 'InspirationGenerator' and 'FancyText'. The arrows are labelled with the word 'renders'. 'InspirationGenerator' node also has two arrows pointing to nodes 'FancyText' and 'Copyright'.
Tree graph with five nodes. Each node represents a component. The root of the tree is App, with two arrows extending from it to 'InspirationGenerator' and 'FancyText'. The arrows are labelled with the word 'renders'. 'InspirationGenerator' node also has two arrows pointing to nodes 'FancyText' and 'Copyright'.

React 建立一個由渲染的元件組成的 _渲染樹_,一個 UI 樹。

從範例應用程式,我們可以構建上述的渲染樹。

樹狀結構由節點組成,每個節點代表一個元件。 AppFancyTextCopyright等等,都是我們樹狀結構中的節點。

React 渲染樹中的根節點是應用程式的 根元件。在這種情況下,根元件是 App,它是 React 渲染的第一個元件。樹狀結構中的每個箭頭都從父元件指向子元件。

深入探討

渲染樹中的 HTML 標籤在哪裡?

您會注意到在上面的渲染樹中,沒有提到每個組件渲染的 HTML 標籤。這是因為渲染樹僅由 React 組件 組成。

React 作為一個 UI 框架,與平台無關。在 react.dev 上,我們展示了渲染到網頁的範例,它使用 HTML 標記作為其 UI 基元。但 React 應用程式也可以渲染到行動或桌面平台,這些平台可能使用不同的 UI 基元,例如 UIViewFrameworkElement

這些平台 UI 基元不是 React 的一部分。無論您的應用程式渲染到哪個平台,React 渲染樹都可以提供對 React 應用程式的洞察。

渲染樹代表 React 應用程式的單次渲染過程。透過 條件渲染,父組件可以根據傳入的資料渲染不同的子組件。

我們可以更新應用程式來有條件地渲染勵志名言或顏色。

import FancyText from './FancyText';
import InspirationGenerator from './InspirationGenerator';
import Copyright from './Copyright';

export default function App() {
  return (
    <>
      <FancyText title text="Get Inspired App" />
      <InspirationGenerator>
        <Copyright year={2004} />
      </InspirationGenerator>
    </>
  );
}

Tree graph with six nodes. The top node of the tree is labelled 'App' with two arrows extending to nodes labelled 'InspirationGenerator' and 'FancyText'. The arrows are solid lines and are labelled with the word 'renders'. 'InspirationGenerator' node also has three arrows. The arrows to nodes 'FancyText' and 'Color' are dashed and labelled with 'renders?'. The last arrow points to the node labelled 'Copyright' and is solid and labelled with 'renders'.
Tree graph with six nodes. The top node of the tree is labelled 'App' with two arrows extending to nodes labelled 'InspirationGenerator' and 'FancyText'. The arrows are solid lines and are labelled with the word 'renders'. 'InspirationGenerator' node also has three arrows. The arrows to nodes 'FancyText' and 'Color' are dashed and labelled with 'renders?'. The last arrow points to the node labelled 'Copyright' and is solid and labelled with 'renders'.

透過條件渲染,在不同的渲染過程中,渲染樹可能會渲染不同的組件。

在此範例中,根據 inspiration.type 的值,我們可能會渲染 <FancyText><Color>。每次渲染過程的渲染樹可能不同。

儘管渲染樹在不同的渲染過程中可能不同,但這些樹通常有助於識別 React 應用程式中的*頂級*和*葉子組件*。頂級組件是最靠近根組件的組件,會影響其下方所有組件的渲染效能,並且通常包含最複雜的邏輯。葉子組件位於樹的底部,沒有子組件,並且經常被重新渲染。

識別這些類別的組件有助於理解應用程式的資料流和效能。

模組依賴樹

在 React 應用程式中,可以用樹狀結構建模的另一種關係是應用程式的模組依賴關係。當我們將組件和邏輯 分解成單獨的檔案 時,我們會建立 JS 模組,我們可以在其中匯出組件、函式或常數。

模組依賴樹中的每個節點都是一個模組,每個分支代表該模組中的一個 import 陳述式。

如果我們使用先前的 Inspirations 應用程式,我們可以構建一個模組依賴樹,簡稱依賴樹。

A tree graph with seven nodes. Each node is labelled with a module name. The top level node of the tree is labelled 'App.js'. There are three arrows pointing to the modules 'InspirationGenerator.js', 'FancyText.js' and 'Copyright.js' and the arrows are labelled with 'imports'. From the 'InspirationGenerator.js' node, there are three arrows that extend to three modules: 'FancyText.js', 'Color.js', and 'inspirations.js'. The arrows are labelled with 'imports'.
A tree graph with seven nodes. Each node is labelled with a module name. The top level node of the tree is labelled 'App.js'. There are three arrows pointing to the modules 'InspirationGenerator.js', 'FancyText.js' and 'Copyright.js' and the arrows are labelled with 'imports'. From the 'InspirationGenerator.js' node, there are three arrows that extend to three modules: 'FancyText.js', 'Color.js', and 'inspirations.js'. The arrows are labelled with 'imports'.

Inspirations 應用程式的模組依賴樹。

樹的根節點是根模組,也稱為入口點檔案。它通常是包含根組件的模組。

與同一個應用程式的渲染樹相比,它們具有相似的結構,但也有一些顯著的差異

  • 構成樹的節點代表模組,而不是組件。
  • 非組件模組,例如 inspirations.js,也呈現在此樹中。渲染樹僅封裝組件。
  • Copyright.js 出現在 App.js 下方,但在渲染樹中,組件 Copyright 出現為 InspirationGenerator 的子組件。這是因為 InspirationGenerator 接受 JSX 作為 子組件屬性,因此它將 Copyright 渲染為子組件,但不匯入模組。

依賴樹可用於確定執行 React 應用程式所需的模組。在構建用於生產環境的 React 應用程式時,通常會有一個構建步驟,將所有必要的 JavaScript 程式碼打包發送到客戶端。負責此工作的工具稱為 打包器,打包器將使用依賴樹來確定應包含哪些模組。

隨著應用程式的增長,通常程式碼包的大小也會增加。大型程式碼包對於客戶端來說下載和執行成本很高。大型程式碼包可能會延遲 UI 的繪製時間。了解應用程式的依賴樹可能有助於除錯這些問題。

總結

  • 樹是表示實體之間關係的常用方法。它們通常用於建模 UI。
  • 渲染樹表示單次渲染過程中 React 組件之間的嵌套關係。
  • 透過條件渲染,渲染樹在不同的渲染過程中可能會發生變化。使用不同的屬性值,組件可能會渲染不同的子組件。
  • 渲染樹有助於識別頂級和葉子組件。頂級組件會影響其下方所有組件的渲染效能,而葉子組件通常會頻繁地重新渲染。識別它們有助於理解和除錯渲染效能。
  • 依賴樹表示 React 應用程式中的模組依賴關係。
  • 構建工具使用依賴樹來打包應用程式發佈所需的程式碼。
  • 依賴樹可用於除錯導致繪製時間變慢的大型程式碼包,並找出最佳化程式碼包的機會。