将你的 UI 理解为树
你的 React 应用正在成型,许多组件相互嵌套。React 是如何跟踪你的应用组件结构的呢?
React 以及许多其他 UI 库将 UI 建模为树。将你的应用视为树有助于理解组件之间的关系。这种理解将帮助你调试未来的概念,如性能和状态管理。
你将学习
- React 如何“看待”组件结构
- 什么是渲染树及其用途
- 什么是模块依赖树及其用途
你的 UI 作为树
树是项目之间的关系模型。UI 通常使用树结构来表示。例如,浏览器使用树结构来建模 HTML(DOM)和 CSS(CSSOM)。移动平台也使用树来表示其视图层次结构。


React 从你的组件创建一个 UI 树。在这个例子中,UI 树随后被用来渲染到 DOM。
与浏览器和移动平台类似,React 也使用树结构来管理和建模 React 应用中组件之间的关系。这些树是理解数据如何在 React 应用中流动以及如何优化渲染和应用大小的有用工具。
渲染树
组件的一个主要特性是能够组合其他组件。当我们嵌套组件时,我们就有了父组件和子组件的概念,其中每个父组件本身可能是另一个组件的子组件。
当我们渲染一个 React 应用时,我们可以将这种关系建模为一棵树,称为渲染树。
这是一个渲染励志名言的 React 应用。


React 创建一个渲染树,一个由已渲染组件组成的 UI 树。
根据示例应用,我们可以构建出上面的渲染树。
树由节点组成,每个节点代表一个组件。App、FancyText、Copyright等等,都是我们树中的节点。
React 渲染树的根节点是应用的根组件。在这个例子中,根组件是App,它是 React 渲染的第一个组件。树中的每个箭头都从父组件指向子组件。
渲染树表示 React 应用程序的单个渲染过程。通过条件渲染,父组件可能会根据传递的数据渲染不同的子组件。
我们可以更新应用程序,以有条件地渲染励志名言或颜色。


通过条件渲染,在不同的渲染过程中,渲染树可能会渲染不同的组件。
在这个例子中,根据 inspiration.type的值,我们可能会渲染<FancyText> 或 <Color>。每次渲染过程的渲染树可能都不同。
尽管渲染树在不同的渲染过程中可能不同,但这些树通常有助于识别 React 应用程序中的顶层 和 叶子组件。顶层组件是离根组件最近的组件,影响其下所有组件的渲染性能,并且通常包含最复杂的逻辑。叶子组件位于树的底部,没有子组件,并且经常被重新渲染。
识别这些组件类别对于理解应用程序的数据流和性能非常有用。
模块依赖树
React 应用中另一种可以用树来建模的关系是应用的模块依赖关系。当我们拆分组件和逻辑到单独的文件时,我们创建了JS 模块,在其中我们可以导出组件、函数或常量。
模块依赖树中的每个节点都是一个模块,每个分支代表该模块中的一个import 语句。
如果我们以前面的 Inspirations 应用为例,我们可以构建一个模块依赖树,或简称为依赖树。


Inspirations 应用的模块依赖树。
树的根节点是根模块,也称为入口文件。它通常是包含根组件的模块。
与同一应用的渲染树相比,结构相似,但存在一些显著差异:
- 构成树的节点代表模块,而非组件。
- 非组件模块,例如
inspirations.js,也会在此树中表示。渲染树仅封装组件。 Copyright.js出现在App.js下方,但在渲染树中,组件Copyright作为InspirationGenerator的子组件出现。这是因为InspirationGenerator接受 JSX 作为子属性,因此它将Copyright渲染为子组件,但并未导入该模块。
依赖树有助于确定运行 React 应用需要哪些模块。在为生产环境构建 React 应用时,通常会有一个构建步骤,将所有必要的 JavaScript 打包以交付给客户端。负责此工作的工具称为打包器,打包器会使用依赖树来确定应包含哪些模块。
随着应用的增长,打包体积通常也会增加。过大的打包体积对于客户端下载和运行来说代价高昂。过大的打包体积可能会延迟用户界面的绘制时间。了解应用的依赖树有助于调试这些问题。
回顾
- 树是表示实体之间关系的常见方式。它们通常用于对用户界面进行建模。
- 渲染树表示单次渲染中 React 组件之间的嵌套关系。
- 在条件渲染下,渲染树可能在不同的渲染中发生变化。使用不同的属性值,组件可能会渲染不同的子组件。
- 渲染树有助于识别顶层组件和叶子组件。顶层组件影响其下所有组件的渲染性能,而叶子组件通常会被频繁重新渲染。识别它们对于理解和调试渲染性能非常有用。
- 依赖树表示 React 应用中的模块依赖关系。
- 构建工具使用依赖树来打包交付应用所需的代码。
- 依赖树有助于调试因打包体积过大而导致的绘制延迟问题,并为优化打包代码提供机会。
