如何解决容器类组件内容为空时margin的空间占用问题
===========================

#### 问题现象

容器类的组件设置了margin属性，当容器内容为空时margin依然会生效占用空间，如何实现当容器组件存在内容时，margin属性生效，容器组件内部为空时，margin不额外占用空间？

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/f8/v3/uxBDR-e-T_CuTiHHRx-hZw/zh-cn_image_0000002628569608.png?HW-CC-KV=V1&HW-CC-Date=20260709T134037Z&HW-CC-Expire=86400&HW-CC-Sign=500A6B2DB2BEC9507B04C3C401F6C545CEFD228D808AC941336792B3805B8D40 "点击放大")

#### 背景知识

布局组件Row、Column、Stack、Flex、List、Swiper等均为可容纳子组件的容器组件。

*   [margin](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#margin)设置组件的外边距属性，支持calc计算。
*   [onAreaChange](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-component-area-change-event#onareachange)组件区域变化时触发该回调，可以获取组件区域的大小。

#### 解决方案

*   方案一：当容器组件**未主动设置宽高**且内部无组件时，其占据显示区域为0。使用onAreaChange获取容器组件的宽高，依据组件宽高来控制margin的值。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/95/v3/MF0L7u1xQ_iF0k1V2gw5Zw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T134037Z&HW-CC-Expire=86400&HW-CC-Sign=92D08A4ADAE7DFCE0B401DF30F56FE2ADAE04BFAD7E645B6B6B1ED0F85E7DAB0)
    
    根据组件宽高的数值来判断容器内部是否有内容，由于**计算精度可能导致的误差**，所以设置比较范围而不是判断是否为零。
    
*   方案二：根据业务逻辑自行判断容器内部是否为空，设置状态变量控制margin属性。
*   方案三：对于List、Swiper等组件，一般是依据数据源来展示，可根据数据源是否为空来设置margin属性。
    
    @Entry
    @Component
    struct PageMargin {
      @State dataSource: string\[\] \= \[\]; _//_ _数据源_
      @State content: boolean \= false; _//_ _自行保存容器内部状态_
      @State rowWidth: number \= 0; _//_ _状态变量，保存容器组件的宽度_
    
      build() {
        Column({ space: 16 }) {
         _ // 方案一_
          Column() {
          _  // 当前Column中无组件_
          }
          .onAreaChange((oldValue: Area, newValue: Area) \=\> {
            this.rowWidth \= newValue.width as number;
            console.info(\`rowWidth: ${this.rowWidth}\`);
          })
          .backgroundColor('#0a59f7')
          .margin(this.rowWidth <\= 1 ? '0' : '20vp'); _// 依据宽度控制margin_
        _//_ _方案二_
          Column({ space: 16 }) {
            Button('toggle')
              .backgroundColor('#0a59f7')
              .onClick(() \=\> {
                this.content \= !this.content;
              });
            if (this.content) {
              Text('hello world');
            }
          }
          .margin(this.content \=== true ? '20vp' : '0');
    
        _  // 方案三_
          Button('add dataSource')
            .backgroundColor('#0a59f7')
            .onClick(() \=\> {
              this.dataSource.push('数据');
            });
          List() {
            ForEach(this.dataSource, (item: string, index: number) \=\> {
              ListItem() {
                Text(item)
                  .onClick(() \=\> {
                    console.info(\`index: ${index}\`);
                  });
              };
            }, (item: string, index) \=\> item \+ index);
          }
          .padding(8)
          .backgroundColor('#f1f3f5')
          .borderRadius(5)
          .margin(this.dataSource.length \=== 0 ? '0' : '20vp');
        }
        .padding(16)
        .height('100%')
        .width('100%');
      }
    }