HarmonyOS 「星办OA」App应用实战18 : Grid 网格布局在企业应用中的实践

HarmonyOS 「星办OA」App应用实战18 : Grid 网格布局在企业应用中的实践 Grid 网格布局在企业应用中的实践一、引言在企业办公应用中网格布局是一种常见且高效的 UI 组织方式。HarmonyOS NEXT 的 ArkUI 框架提供了Grid组件它支持行列模板配置、自适应布局和响应式设计非常适合用于展示网格状的功能入口、数据卡片等场景。本文将以星办 OA企业办公审批项目中的HomePage快捷发起区域的 Grid 布局为实际案例深入解析Grid组件的使用方式、行列模板配置、自适应布局以及响应式设计。二、Grid 组件的基本概念2.1 什么是 GridGrid是 ArkUI 框架中用于实现网格布局的容器组件。它可以将子组件按照行和列的规则排列形成整齐的网格结构。Grid组件支持自定义行列模板、间距控制、滚动等功能。构造函数签名Grid({ scroller?: Scroller })2.2 GridItem 的概念GridItem是Grid的子组件用于表示网格中的单个单元格。每个GridItem只能包含一个根组件但根组件可以包含任意复杂的子组件树。三、快捷发起区域的实际实现3.1 使用 Row 实现的网格布局在星办 OA的HomePage中快捷发起区域使用了Row组件来模拟网格布局而不是直接使用Grid组件Builder private buildQuickStart() { Column({ space: 14 }) { this.buildSectionTitle(快捷发起, 常用审批) Column({ space: 12 }) { Row({ space: 12 }) { this.buildQuickAction(请假, 休假与调休, 假) this.buildQuickAction(报销, 费用与票据, 报) this.buildQuickAction(出差, 行程与预算, 差) this.buildQuickAction(采购, 物品与服务, 采) } .width(100%) Row({ space: 12 }) { this.buildQuickActionSmall(加班, 加) this.buildQuickActionSmall(用印, 印) this.buildQuickActionSmall(报销, 报) this.buildQuickActionSmall(出差, 差) } .width(100%) } } .width(100%) .padding(16) .borderRadius(18) .backgroundColor(Color.White) }这里通过两行Row组件每行 4 列实现了 2 行 4 列的网格布局。第一行是主功能入口请假、报销、出差、采购第二行是次要功能入口加班、用印、报销、出差。3.2 使用 Flex 实现的网格布局在ApprovalCreatePage中审批类型的选择器使用了Flex组件来实现网格布局Builder private buildTypeSelector() { Column({ space: 12 }) { Row() { Text(审批类型).fontSize(16).fontWeight(FontWeight.Bold).fontColor(#182431) Text(必选).fontSize(11).fontColor(#E5484D) } .width(100%) .justifyContent(FlexAlign.SpaceBetween) Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) { ForEach(this.types, (type: string) { Text(type) .width(30%) .height(38) .margin({ right: 3%, bottom: 10 }) .textAlign(TextAlign.Center) .fontSize(14) .fontWeight(this.selectedType type ? FontWeight.Medium : FontWeight.Regular) .fontColor(this.selectedType type ? #2459E0 : #667085) .border({ width: 1, color: this.selectedType type ? #3B6FF5 : #EAECF0 }) .borderRadius(10) .backgroundColor(this.selectedType type ? #F1F4FF : Color.White) .onClick(() { this.selectedType type this.summary }) }, (type: string) type) } } .width(100%) .padding(15) .borderRadius(16) .backgroundColor(Color.White) }这里通过Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start })配合width(30%)和margin({ right: 3% })实现了每行 3 列的网格布局。每个类型项占 30% 宽度右侧 3% 间距合计 99%接近 100%。四、Grid 组件的详细配置4.1 行列模板配置Grid组件支持通过columnsTemplate和rowsTemplate属性来配置行列模板Grid() { // 网格内容 } .columnsTemplate(1fr 1fr 1fr 1fr) // 4列等宽 .rowsTemplate(1fr 1fr) // 2行等高 .columnsGap(12) // 列间距 .rowsGap(12) // 行间距其中columnsTemplate和rowsTemplate使用字符串模板语法1fr 1fr 1fr 1fr4 列等宽每列占 1 份可用空间100px 1fr 2fr第 1 列固定 100px第 2 列占 1 份第 3 列占 2 份repeat(3, 1fr)3 列等宽repeat 语法4.2 间距配置Grid组件支持配置行间距和列间距columnsGap列间距rowsGap行间距4.3 自适应布局Grid组件支持通过onGridItemIndexChange事件监听网格项的变化实现自适应布局。当网格容器的尺寸变化时可以根据可用空间自动调整网格的列数。五、Row 模拟网格 vs 原生 Grid 组件5.1 对比分析特性Row 模拟网格原生 Grid 组件列数固定手动控制通过模板配置滚动支持需要 Scroll 包装内置支持自适应需要手动计算支持行列模板使用场景固定列数的小型网格数据量大的网格5.2 选择建议在星办 OA项目中快捷发起区域使用Row模拟网格而不是原生Grid组件是因为列数固定快捷发起区域固定为 4 列不需要动态调整数据量小只有 8 个功能入口不需要虚拟滚动布局简单每行独立不需要复杂的跨行跨列配置对于数据量大、需要虚拟滚动或复杂行列配置的场景建议使用原生的Grid组件。六、Grid 的响应式设计6.1 响应式列数在响应式设计中Grid 可以根据屏幕宽度自动调整列数。例如Grid() { ForEach(this.items, (item: GridItemData) { GridItem() { this.buildGridItem(item) } }) } .columnsTemplate(this.getColumnsTemplate()) .rowsGap(12) .columnsGap(12)private getColumnsTemplate(): string { let width: number this.getUIContext().getWindowSizeSync().width if (width 1000) { return 1fr 1fr 1fr 1fr 1fr // 大屏 5 列 } if (width 600) { return 1fr 1fr 1fr 1fr // 中屏 4 列 } return 1fr 1fr 1fr // 小屏 3 列 }6.2 自适应间距除了列数间距也可以根据屏幕尺寸调整private getGridGap(): number { let width: number this.getUIContext().getWindowSizeSync().width if (width 1000) { return 16 // 大屏大间距 } return 12 // 小屏小间距 }七、Grid 的高级用法7.1 跨行跨列GridItem支持通过columnStart、columnEnd、rowStart、rowEnd属性实现跨行跨列Grid() { GridItem() { Text(1).fontSize(30) } GridItem() { Text(2).fontSize(30) } .columnStart(1) // 从第 2 列开始 .columnEnd(2) // 到第 3 列结束跨 2 列 } .columnsTemplate(1fr 1fr 1fr) .rowsTemplate(1fr 1fr)7.2 虚拟滚动当网格数据量很大时Grid组件支持虚拟滚动Grid() { ForEach(this.largeDataSet, (item: DataItem) { GridItem() { Text(item.label) } }) } .columnsTemplate(1fr 1fr 1fr) .rowsTemplate(1fr 1fr 1fr 1fr 1fr)Grid的虚拟滚动机制与List类似只渲染当前可见区域的网格项大幅提升性能。八、企业应用中的网格布局模式8.1 功能入口网格这是星办 OA中快捷发起区域的模式适用于展示多个功能入口每行 4 列每列等宽每个入口包含图标和文字标签点击入口跳转到对应功能页面8.2 数据展示网格适用于展示数据卡片或统计信息Grid() { ForEach(this.statCards, (card: StatCard) { GridItem() { Column({ space: 8 }) { Text(card.value).fontSize(28).fontWeight(FontWeight.Bold) Text(card.label).fontSize(12).fontColor(#667085) } .padding(16).borderRadius(12).backgroundColor(Color.White) } }) } .columnsTemplate(1fr 1fr) .rowsGap(12).columnsGap(12)8.3 审批类型选择器星办 OA中审批类型选择器使用了 Flex 换行实现网格适用于需要动态选择多个选项的场景每行 3 列选中状态高亮点击切换选中项九、最佳实践9.1 选择合适的布局方案固定列数的小型网格 10 项使用Row模拟固定列数的大型网格 10 项使用Grid组件需要自适应的网格使用Grid组件配合响应式模板需要换行的网格使用Flex配合FlexWrap.Wrap9.2 性能优化对于大型网格使用Grid组件的虚拟滚动特性为GridItem提供稳定的 key帮助框架识别哪些项需要更新避免在GridItem内部创建过于复杂的组件树9.3 视觉一致性保持网格项之间的间距一致使用统一的卡片样式圆角、阴影、背景色确保网格项在视觉上具有相同的权重十、总结Grid网格布局是 ArkUI 框架中重要的布局方式特别适合企业应用中功能入口、数据卡片等场景。通过星办 OA项目中快捷发起区域和审批类型选择器的实际代码分析我们深入理解了多种网格布局的实现方式。在星办 OA中快捷发起区域使用Row模拟网格布局审批类型选择器使用Flex换行实现网格它们各有适用场景。对于数据量大、需要虚拟滚动或复杂行列配置的场景Grid组件是更好的选择。理解网格布局的原理、掌握行列模板配置、合理选择布局方案是构建高质量 HarmonyOS NEXT 应用界面布局的基础。