将你的用户界面理解为一棵树

你的 React 应用正在成型,许多组件相互嵌套。React 是如何跟踪你应用的组件结构的?

🌐 Your React app is taking shape with many components being nested within each other. How does React keep track of your app’s component structure?

React 和许多其他 UI 库将 UI 建模为一棵树。把你的应用看作一棵树有助于理解组件之间的关系。这种理解将帮助你调试未来的概念,例如性能和状态管理。

🌐 React, and many other UI libraries, model UI as a tree. Thinking of your app as a tree is useful for understanding the relationship between components. This understanding will help you debug future concepts like performance and state management.

你将学习到

  • React 如何“看待”组件结构
  • 渲染树是什么以及它有什么用处
  • 什么是模块依赖树以及它的用途

你的用户界面就像一棵树

🌐 Your UI as a tree

树是一种项目之间的关系模型。用户界面通常使用树结构表示。例如,浏览器使用树结构来建模 HTML(DOM)和 CSS(CSSOM)。移动平台也使用树来表示它们的视图层次结构。

🌐 Trees are a relationship model between items. The UI is often represented using tree structures. For example, browsers use tree structures to model HTML (DOM) and CSS (CSSOM). Mobile platforms also use trees to represent their view hierarchy.

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 应用中流动以及如何优化渲染和应用大小的有用工具。

🌐 Like browsers and mobile platforms, React also uses tree structures to manage and model the relationship between components in a React app. These trees are useful tools to understand how data flows through a React app and how to optimize rendering and app size.

渲染树

🌐 The Render Tree

组件的一个主要特性是能够将组件组合成其他组件。当我们嵌套组件时,我们就有了父组件和子组件的概念,其中每个父组件本身也可能是另一个组件的子组件。

🌐 A major feature of components is the ability to compose components of other components. As we nest components, we have the concept of parent and child components, where each parent component may itself be a child of another component.

当我们渲染 React 应用时,我们可以在树中建模这种关系,称为渲染树。

🌐 When we render a React app, we can model this relationship in a tree, known as the render tree.

这是一个 React 应用,可以渲染励志名言。

🌐 Here is a React app that renders inspirational quotes.

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 树,由渲染的组件组成。

🌐 React creates a render tree, a UI tree, composed of the rendered components.

从示例应用中,我们可以构建上面的渲染树。

🌐 From the example app, we can construct the above render tree.

这棵树由节点组成,每个节点代表一个组件。AppFancyTextCopyright,仅举几例,都是我们树中的节点。

🌐 The tree is composed of nodes, each of which represents a component. App, FancyText, Copyright, to name a few, are all nodes in our tree.

在 React 渲染树中,根节点是应用的根组件。在这种情况下,根组件是 App,它是 React 渲染的第一个组件。树中的每个箭头都从父组件指向子组件。

🌐 The root node in a React render tree is the root component of the app. In this case, the root component is App and it is the first component React renders. Each arrow in the tree points from a parent component to a child component.

深入研究

渲染树中的 HTML 标签在哪里?

🌐 Where are the HTML tags in the render tree?

你会注意到在上面的渲染树中,没有提到每个组件渲染的 HTML 标签。这是因为渲染树仅由 React 组件 组成。

🌐 You’ll notice in the above render tree, there is no mention of the HTML tags that each component renders. This is because the render tree is only composed of React components.

React 作为一个 UI 框架,对平台是不可知的。在 react.dev 上,我们展示了渲染到网页的示例,网页使用 HTML 标记作为其 UI 原语。但一个 React 应用同样可以渲染到移动或桌面平台,这些平台可能使用不同的 UI 原语,例如 UIViewFrameworkElement

🌐 React, as a UI framework, is platform agnostic. On react.dev, we showcase examples that render to the web, which uses HTML markup as its UI primitives. But a React app could just as likely render to a mobile or desktop platform, which may use different UI primitives like UIView or FrameworkElement.

这些平台 UI 基元不是 React 的一部分。无论你的应用渲染到哪个平台,React 渲染树都可以为我们的 React 应用提供洞察。

🌐 These platform UI primitives are not a part of React. React render trees can provide insight to our React app regardless of what platform your app renders to.

渲染树表示 React 应用的单次渲染过程。通过条件渲染,父组件可以根据传入的数据渲染不同的子组件。

🌐 A render tree represents a single render pass of a React application. With conditional rendering, a parent component may render different children depending on the data passed.

我们可以更新应用以有条件地渲染鼓舞人心的引言或颜色。

🌐 We can update the app to conditionally render either an inspirational quote or color.

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'.

通过条件渲染,在不同的渲染中,渲染树可能会渲染不同的组件。

🌐 With conditional rendering, across different renders, the render tree may render different components.

在此示例中,取决于 inspiration.type 是什么,我们可能会渲染 <FancyText><Color>。每次渲染过程的渲染树可能不同。

🌐 In this example, depending on what inspiration.type is, we may render <FancyText> or <Color>. The render tree may be different for each render pass.

虽然渲染树在不同的渲染过程中可能会有所不同,但这些树通常有助于识别 React 应用中的顶层组件叶子组件。顶层组件是最接近根组件的组件,会影响其下所有组件的渲染性能,并且通常包含最多的复杂性。叶子组件位于树的底部,没有子组件,且通常会被频繁重新渲染。

🌐 Although render trees may differ across render passes, these trees are generally helpful for identifying what the top-level and leaf components are in a React app. Top-level components are the components nearest to the root component and affect the rendering performance of all the components beneath them and often contain the most complexity. Leaf components are near the bottom of the tree and have no child components and are often frequently re-rendered.

识别这些组件类别对于了解应用的数据流和性能很有用。

🌐 Identifying these categories of components are useful for understanding data flow and performance of your app.

模块依赖树

🌐 The Module Dependency Tree

在 React 应用中,另一种可以用树状结构建模的关系是应用的模块依赖。当我们将组件和逻辑拆分到不同的文件中时,我们会创建可以导出组件、函数或常量的 JS 模块。

🌐 Another relationship in a React app that can be modeled with a tree are an app’s module dependencies. As we break up our components and logic into separate files, we create JS modules where we may export components, functions, or constants.

模块依赖树中的每个节点都是一个模块,每条分支表示该模块中的一个 import 语句。

🌐 Each node in a module dependency tree is a module and each branch represents an import statement in that module.

如果我们采用之前的 Inspirations 应用,我们可以构建一个模块依赖树,简称依赖树。

🌐 If we take the previous Inspirations app, we can build a module dependency tree, or dependency tree for short.

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 应用的模块依赖树。

🌐 The module dependency tree for the Inspirations app.

树的根节点是根模块,也称为入口文件。它通常是包含根组件的模块。

🌐 The root node of the tree is the root module, also known as the entrypoint file. It often is the module that contains the root component.

与同一应用的渲染树相比,结构相似,但有一些显着差异:

🌐 Comparing to the render tree of the same app, there are similar structures but some notable differences:

  • 组成树的节点代表模块,而不是组件。
  • 非组件模块,如 inspirations.js,也在此树中表示。渲染树只封装组件。
  • Copyright.js 出现在 App.js 下,但在渲染树中,组件 Copyright 出现为 InspirationGenerator 的子组件。这是因为 InspirationGenerator 接受 JSX 作为 children props,所以它将 Copyright 渲染为子组件,但并没有导入该模块。

依赖树对于确定运行你的 React 应用所需的模块非常有用。在为生产环境构建 React 应用时,通常会有一个构建步骤,将所有必要的 JavaScript 打包以发送到客户端。负责此任务的工具称为打包工具,打包工具将使用依赖树来确定应包含哪些模块。

🌐 Dependency trees are useful to determine what modules are necessary to run your React app. When building a React app for production, there is typically a build step that will bundle all the necessary JavaScript to ship to the client. The tool responsible for this is called a bundler, and bundlers will use the dependency tree to determine what modules should be included.

随着你的应用增长,通常打包包的大小也会增加。大的打包包对客户端来说下载和运行成本高。大的打包包可能会延迟你的用户界面绘制的时间。了解你的应用依赖树的情况可能有助于调试这些问题。

🌐 As your app grows, often the bundle size does too. Large bundle sizes are expensive for a client to download and run. Large bundle sizes can delay the time for your UI to get drawn. Getting a sense of your app’s dependency tree may help with debugging these issues.

回顾

  • 树是一种常见的表示实体之间关系的方式。它们常用于建模用户界面。
  • 渲染树表示单个渲染中 React 组件之间的嵌套关系。
  • 使用条件渲染时,渲染树可能在不同的渲染中发生变化。随着不同的属性值,组件可能渲染不同的子组件。
  • 渲染树有助于识别哪些是顶层组件和叶子组件。顶层组件会影响其下所有组件的渲染性能,而叶子组件则经常被重新渲染。识别它们对于理解和调试渲染性能非常有用。
  • 依赖树表示 React 应用中的模块依赖。
  • 构建工具使用依赖树来打包交付应用所需的代码。
  • 依赖树对于调试大的打包包非常有用,因为它们会减慢绘制时间并公开优化打包代码的机会。