
#我的鸿蒙开发手记#Flex布局性能优化 原创 精华
弹性布局(FLex)提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。常用于页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等。但Flex布局的不合理使用也会增加对性能的损耗,那么如何才能通过优化来减少性能的过度损耗呢?
一、应该考虑减少嵌套层级。
Flex布局如果嵌套太多层,可能会导致渲染变慢。可能的话,应该简化结构,用更少的容器。
二、列表渲染场景。
如果Flex布局用于长列表,比如用ForEach渲染很多项,没有做优化的话,滚动时可能会有卡顿。这时候应该使用列表项复用,比如List组件或者LazyForEach,只渲染可视区域内的项,减少内存和计算量。同时,给列表项设置固定尺寸,避免动态计算高度或宽度,这样滚动会更流畅。
List() {
LazyForEach(dataSource, (item) => {
ListItem() {
Text(item.name).height(80) // 固定高度
}
})
}
三、避免不必要的重新布局。
Flex的某些属性会触发二次布局,这样会导致布局效率下降。
(1)flexGrow:设置父容器的剩余空间分配给此属性所在组件的比例。用于分配父组件的剩余空间。
Flex({ wrap: FlexWrap.NoWrap }) {
Text("A")
.height(40)
.backgroundColor(0xD2B48C)
.width(100)
.flexGrow(1)
Text("B")
.height(40)
.width(100)
.flexGrow(2)
.backgroundColor(0xF5DEB3)
Text("C")
.height(40)
.backgroundColor(Color.Red)
.width(100)
}.width(400)
.height(100)
.backgroundColor("#efefef")
如图父容器的宽度为400,A、B、C三个组件的宽度都为100,如果不设置flexGrow属性,会有100的剩余空间。当A的flexGrow为1,B的FlexGrow为3时,A、B会以1:3的比例来分剩余的100空间。A的宽度为100+1001/4=125,B的宽度为100+1003/4=175。再次分配空间会导致二次布局。
(2)flexShrink: 当父容器空间不足时,子元素的压缩比例
Flex({ wrap: FlexWrap.NoWrap }) {
Text("A")
.height(40)
.backgroundColor(0xD2B48C)
.width(200)
Text("B")
.height(40)
.width(200)
.flexShrink(1)
.backgroundColor(0xF5DEB3)
Text("C")
.height(40)
.backgroundColor(Color.Red)
.width(200)
.flexShrink(3)
}.width(400)
.height(100)
.backgroundColor("#efefef")
如图父容器的宽度为400,A、B、C的宽度都为200,由于子组件宽度和大于父组件宽度,当不设置flexShrink时,ABC被平均压缩。当B的flexShrink为1,C的flexShrink为3时,B的宽度为200-2001/4=150,C的宽度为200-2003/4=50。
对不变的部分设置 flexShrink: 0
,防止压缩计算。
所以频繁修改 flexGrow
、flexShrink
或动态尺寸属性会导致重复布局计算。尽量为子组件设置固定尺寸(如 width: '100%'
或 height: 200
)
// 不推荐:动态调整 flexGrow
@State growValue: number = 1;
Flex() {
Text('Dynamic').flexGrow(this.growValue)
}
// 推荐:提前计算静态值
四、用visibility
替代 if/else
条件渲染,减少节点销毁/重建。
// 不推荐:频繁切换条件渲染
if (this.show) {
Text('Content')
}
// 推荐:控制显隐
Text('Content').visibility(this.show ? Visibility.Visible : Visibility.None)
五、替代Flex容器的使用
优先使用Column/Row组件
Flex容器默认可能因子组件伸缩属性触发二次布局(如空间不足时调整flexShrink属性),而Column/Row组件在单轴布局中更高效,可避免不必要的二次计算
