React Native 布局引擎负责计算 React Native 应用程序中 UI 组件的大小和位置。其核心是 Yoga,一个跨平台的 Flexbox 布局算法实现。本文档将解释 Yoga 的工作原理、核心组件以及布局计算过程。
有关 UI 组件和样式的信息,请参阅 UI 组件和样式。有关特定平台实现的信息,请参阅 Android 实现 和 iOS 实现。
Yoga 是一个用 C++ 编写的独立布局引擎,实现了 Flexbox 规范。它根据视图的样式属性、约束以及它们在组件层次结构中与其他视图的关系来计算视图的位置和大小。Yoga 使 React Native 能够在 iOS 和 Android 上提供一致的布局体验。
Yoga 的主要特点包括:
来源
yoga::Node 类是布局系统的基本构建块。React Native 中的每个视图都对应于布局树中的一个 Yoga 节点。
Node 的关键特征
├── Node properties
│ ├── Style (positioning, dimensions, margins, etc.)
│ ├── Layout results (final position and size)
│ ├── Children (nested nodes)
│ ├── Config (layout behavior settings)
│ └── Measurement functions (for custom measuring)
来源
yoga::Style 类封装了所有影响布局的样式属性,包括:
这些属性决定了一个节点及其子节点的布局方式。
来源
LayoutResults 类存储了节点的计算布局信息
在布局计算之后,这些值表示 UI 组件的最终位置和大小。
来源
yoga::Config 类包含 Yoga 引擎的配置设置
Config 设置会影响布局的计算和渲染方式。
来源
Yoga 中的布局计算遵循一个多步骤过程,以确定布局树中每个节点的尺寸和位置。
来源
初始配置:布局过程从使用适当的比例因子和布局方向配置 Yoga 树开始。
测量阶段:
布局阶段:
Flex 布局计算:
完成:
来源
Yoga 实现的 CSS Flexbox 规范,并针对移动平台进行了一些调整。核心概念保持不变:
`FlexDirection` 决定了子节点布局的主要轴
Row:从左到右(在 LTR 语言中)Column:从上到下RowReverse:从右到左(在 LTR 语言中)ColumnReverse:从下到上`FlexDirection` 会影响 `justifyContent` 和 `alignItems` 等其他属性的行为。
来源
Yoga 根据 Flex 属性在主轴上分配空间
Flex Grow:确定当存在额外空间时,节点相对于兄弟节点增长的程度
Flex Shrink:确定在空间受限时,节点相对于兄弟节点收缩的程度
Flex Basis:节点在增长或收缩之前的初始主尺寸
分配算法实现在 `distributeFreeSpaceFirstPass()` 和 `distributeFreeSpaceSecondPass()` 函数中。
来源
Yoga 实现了一些对齐属性
Justify Content:在主轴上对齐项目
FlexStart、Center、FlexEnd、SpaceBetween、SpaceAround、SpaceEvenlyAlign Items:在交叉轴上对齐项目
FlexStart、Center、FlexEnd、Stretch、BaselineAlign Self:允许单个项目覆盖父级的 align-items 设置
对齐逻辑在确定大小和主轴位置后应用。
来源
布局引擎通过 Shadow Node 树系统与 React Native 集成。
YogaLayoutableShadowNode 类充当 React Native 的 Shadow Node 系统与 Yoga 之间的桥梁
├── YogaLayoutableShadowNode
│ ├── yogaNode_ (yoga::Node instance)
│ ├── yogaConfig_ (Yoga configuration)
│ ├── updateYogaProps() (converts React props to Yoga style)
│ ├── updateYogaChildren() (syncs children with Yoga tree)
│ └── layoutTree() (triggers Yoga layout calculation)
来源
当 React Native 组件需要进行布局时
YGNodeCalculateLayout()来源
当节点具有 position: 'absolute' 时,它将脱离文档流,并根据其相对于包含块的约束(上、左、下、右)进行定位。
layoutAbsoluteChild() 函数
来源
当使用 alignItems: 'baseline' 时,子项将对齐,使其文本基线匹配。这对于不同大小的文本尤其有用。
calculateBaseline() 函数
来源
为了确保屏幕上清晰的渲染,布局值会与像素网格对齐
roundLayoutResultsToPixelGrid() 处理整个布局树来源
| 属性 | 描述 | 对布局的影响 |
|---|---|---|
flexDirection | 主轴方向 | 决定了项目的流动方向 |
justifyContent | 主轴上的对齐 | 在主轴上对齐项目 |
alignItems | 交叉轴上的对齐 | 在垂直于主轴的方向上定位项目 |
flexGrow | 增长能力 | 按比例占用可用空间 |
flexShrink | 收缩能力 | 在受到约束时按比例释放空间 |
flexBasis | 初始主尺寸 | 增长/收缩前的起始尺寸 |
position | 定位模式 | 'relative'(默认)或 'absolute' |
width/height | 尺寸 | 如果指定了则为固定尺寸 |
margin | 节点周围的空间 | 在节点边框外创建空间 |
padding | 节点内部的空间 | 在节点边框内创建空间 |
来源
Yoga 包含多项优化以提高布局性能
这些优化对于维持流畅的用户界面性能至关重要,尤其是在处理复杂或深度嵌套的布局时。
来源