你的 React 应用正在成型,许多组件彼此嵌套。React 如何跟踪应用程序的组件结构?
React 和许多其他 UI 库将 UI 建模为一棵树。将你的应用程序视为一棵树有助于理解组件之间的关系。这种理解将帮助你调试未来的概念,例如性能和状态管理。
你将学习
- React 如何“查看”组件结构
- 渲染树是什么以及它有什么用
- 模块依赖树是什么以及它有什么用
你的 UI 作为一棵树
树是项目之间的关系模型,UI 通常使用树结构表示。例如,浏览器使用树结构来建模 HTML (DOM) 和 CSS (CSSOM)。移动平台也使用树来表示其视图层次结构。
与浏览器和移动平台一样,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> </> ); }
从示例应用程序中,我们可以构建上面的渲染树。
这棵树由节点组成,每个节点代表一个组件。App
、FancyText
、Copyright
(仅举几例)都是我们树中的节点。
React 渲染树中的根节点是应用程序的根组件。在本例中,根组件是App
,它是 React 首先渲染的组件。树中的每个箭头都指向从父组件到子组件。
深入探讨
你会注意到,在上面的渲染树中,没有提及每个组件渲染的HTML标签。这是因为渲染树仅由React 组件组成。
React作为一个UI框架,是平台无关的。在react.dev上,我们展示了渲染到web的示例,它使用HTML标记作为其UI原语。但是,React应用程序也可能渲染到移动或桌面平台,这些平台可能使用不同的UI原语,例如UIView或FrameworkElement。
这些平台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> </> ); }
在这个例子中,根据inspiration.type
的值,我们可能会渲染<FancyText>
或<Color>
。每个渲染过程的渲染树可能都不同。
尽管渲染树在不同的渲染过程中可能有所不同,但这些树通常有助于识别React应用程序中的顶级和叶子组件。顶级组件是最靠近根组件的组件,会影响其下方所有组件的渲染性能,并且通常包含最复杂的逻辑。叶子组件位于树的底部,没有子组件,并且经常被重新渲染。
识别这些类别的组件有助于理解应用程序的数据流和性能。
模块依赖树
React应用程序中另一种可以用树表示的关系是应用程序的模块依赖关系。当我们将组件和逻辑分解成单独的文件时,我们创建了JS模块,我们可以在其中导出组件、函数或常量。
模块依赖树中的每个节点都是一个模块,每个分支代表该模块中的import
语句。
如果我们采用之前的Inspirations应用程序,我们可以构建一个模块依赖树,或简称依赖树。
树的根节点是根模块,也称为入口文件。它通常是包含根组件的模块。
与同一个应用程序的渲染树相比,它们具有相似的结构,但也有一些显著的差异。
- 构成树的节点代表模块,而不是组件。
- 非组件模块,例如
inspirations.js
,也在这个树中表示。渲染树只包含组件。 Copyright.js
出现在App.js
下,但在渲染树中,组件Copyright
作为InspirationGenerator
的子组件出现。这是因为InspirationGenerator
接受JSX作为子组件props,因此它将Copyright
渲染为子组件,但不会导入模块。
依赖树有助于确定运行React应用程序所需的模块。构建用于生产的React应用程序时,通常会有一个构建步骤来捆绑所有必要的JavaScript以交付给客户端。负责此操作的工具称为打包器,打包器将使用依赖树来确定应包含哪些模块。
随着应用程序的增长,捆绑包的大小通常也会增加。大型捆绑包对于客户端下载和运行来说成本很高。大型捆绑包可能会延迟UI的绘制时间。了解应用程序的依赖树可能有助于调试这些问题。
总结
- 树是表示实体之间关系的一种常用方法。它们常用于建模UI。
- 渲染树表示单个渲染过程中React组件之间的嵌套关系。
- 使用条件渲染,渲染树在不同的渲染过程中可能会发生变化。使用不同的prop值,组件可能会渲染不同的子组件。
- 渲染树有助于识别顶级组件和叶子组件。顶级组件会影响其下方所有组件的渲染性能,而叶子组件则经常被重新渲染。识别它们对于理解和调试渲染性能非常有用。
- 依赖树表示React应用程序中的模块依赖关系。
- 依赖树由构建工具用来捆绑交付应用程序所需的代码。
- 依赖树有助于调试大型捆绑包大小(这些大小会减慢绘制速度),并为优化捆绑的代码提供机会。