第二板斧:尽量减少布局的嵌套层数
在进行页面布局开发时,应该去除冗余的布局嵌套,使用相对布局、绝对定位、自定义布局、Grid、GridRow等扁平化布局,减少布局的嵌套层数,避免系统绘制更多的布局组件,达到优化性能(详细介绍可参考文章: 优化布局性能)、减少内存占用的目的。
移除冗余节点
应该删除冗余的布局嵌套,例如build最外层的无用容器嵌套、无用的Stack或Column嵌套等,减少布局层数。
删除无用的Stack/Column/Row嵌套
例如可能会在Row容器包含一个同样也是Row容器的子级。这种嵌套实际是多余的,并且会给布局层次结构造成不必要的开销。示例代码如下:
// 反例
Row() {
Row() {
Text()
Text()
}
Text()
}
// 正例
Row() {
Text()
Text()
Text()
}
删除build函数中最外层无用容器嵌套
在开发过程中,布局的实现往往嵌套使用大量的自定义组件,build中冗余的最外层无用容器会大大增强嵌套层级,应该删除。
反例代码如下:
@Component
struct ComponentA {
build() {
Column() {
ComponentB();
}
}
}
@Component
struct ComponentB {
build() {
Column() {
Text('');
}
}
}
正例代码如下:
@Component
struct ComponentA {
build() {
Column() {
ComponentB();
}
}
}
@Component
struct ComponentB {
build() {
Text('');
}
}
使用扁平化布局减少节点数
使用Column/Row替代Flex构建线性布局
由于Flex本身带来的二次布局的影响,Flex的性能明显低于Column和Row容器,因此推荐使用Column/Row替代Flex构建线性布局(详细介绍可参考文章: Flex布局性能提升使用指导)。
反例代码如下:
@Entry
@Component
struct MyComponent {
build() {
Flex({ direction: FlexDirection.Column }) {
Flex().width(300).height(200).backgroundColor(Color.Pink)
Flex().width(300).height(200).backgroundColor(Color.Yellow)
Flex().width(300).height(200).backgroundColor(Color.Grey)
}
}
}
正例代码如下:
@Entry
@Component
struct MyComponent {
build() {
Column() {
Row().width(300).height(200).backgroundColor(Color.Pink)
Row().width(300).height(200).backgroundColor(Color.Yellow)
Row().width(300).height(200).backgroundColor(Color.Grey)
}
}
}
使用Flex、List、Grid、RelativeContainer、绝对布局和自定义布局等构建复杂布局
复杂布局提供了场景化的能力(详细介绍可参考文章: 优化布局性能),解决一种或者多种布局场景:
- 使用Flex构建弹性布局;
- List既具备线性布局的特点,同时支持懒加载和滑动的能力;
- Grid/GridItem提供了宫格布局的能力,同时也支持懒加载和滑动能力;
- RelativeContainer是一种相对布局,通过描述各个内容组件间相互关系来指导内容元素的布局过程,可从横纵两个方面进行布局描述,是一种二维布局算法;
反例代码如下:
@Entry
@Component
struct AspectRatioExample12 {
@State children: Number[] = Array.from(Array<number>(900), (v, k) => k);
build() {
Scroll() {
Grid() {
ForEach(this.children, (item: Number[]) => {
GridItem() {
Stack() {
Stack() {
Stack() {
Text(item.toString())
}.size({ width: "100%"})
}.backgroundColor(Color.Yellow)
}.backgroundColor(Color.Pink)
}
}, (item: string) => item)
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(0)
.rowsGap(0)
.size({ width: "100%", height: "100%" })
}
}
}
正例代码如下:
@Entry
@Component
struct AspectRatioExample11 {
@State children: Number[] = Array.from(Array<number>(900), (v, k) => k);
build() {
Scroll() {
Grid() {
ForEach(this.children, (item: Number[]) => {
GridItem() {
Text(item.toString())
}.backgroundColor(Color.Yellow)
}, (item: string) => item)
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(0)
.rowsGap(0)
.size({ width: "100%", height: "100%" })
}
}
}