img

目录

  • 案例介绍
  • 代码实现
  • 代码详解
  • 数据结构设计
  • 规格选择区布局
  • 交互实现
  • 总结

案例介绍

在电商应用中,规格选择区是用户选择商品具体型号、颜色等属性的关键区域。本篇文章将详细讲解如何使用HarmonyOS NEXT的Column和Flex组件构建一个专业的商品详情页规格选择区,实现规格选项的动态渲染和交互效果。

代码实现

@Entry
@Component
struct ProductDetail {
  // 商品信息
  @State product: {
    title: string,
    price: number,
    originalPrice: number,
    sales: number,
    description: string,
    specs: Array<{
      name: string,
      options: Array<string>
    }>
  } = {
    title: '2024新款智能手表',
    price: 999.00,
    originalPrice: 1299.00,
    sales: 1580,
    description: '高清大屏,续航持久,智能监测,运动计步',
    specs: [
      {
        name: '颜色',
        options: ['曜石黑', '星空银', '玫瑰金']
      },
      {
        name: '尺寸',
        options: ['41mm', '45mm']
      }
    ]
  }

  // 选中的规格
  @State selectedSpecs: Record<string, string> = {}

  build() {
    Column() {
      // 规格选择区
      Column() {
        Text('规格选择')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .margin({ bottom: 15 })

        ForEach(this.product.specs, (spec) => {
          Column() {
            Text(spec.name)
              .fontSize(14)
              .fontColor('#666666')
              .margin({ bottom: 10 })

            Flex({ wrap: FlexWrap.Wrap }) {
              ForEach(spec.options, (option) => {
                Text(option)
                  .fontSize(14)
                  .padding(10)
                  .backgroundColor(this.selectedSpecs[spec.name] === option ? '#FFE4E4' : '#F5F5F5')
                  .fontColor(this.selectedSpecs[spec.name] === option ? '#FF0000' : '#333333')
                  .borderRadius(5)
                  .margin({ right: 10, bottom: 10 })
                  .onClick(() => {
                    this.selectedSpecs[spec.name] = option
                  })
              })
            }
          }
          .margin({ bottom: 20 })
        })
      }
      .width('100%')
      .padding(15)
      .backgroundColor(Color.White)
      .margin({ top: 10 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

代码详解

数据结构设计

我们使用两个关键的状态变量来管理规格选择区:

  1. 商品规格数据

    @State product: {
    // 其他属性...
    specs: Array<{
     name: string,        // 规格名称(如颜色、尺寸)
     options: Array<string> // 规格选项(如黑色、白色)
    }>
    }
    
  2. 选中规格状态

    @State selectedSpecs: Record<string, string> = {}
    

    这是一个键值对对象,键为规格名称,值为选中的选项。例如:{"颜色": "曜石黑", "尺寸": "41mm"}

规格选择区布局

Column() {
  Text('规格选择')
    .fontSize(16)
    .fontWeight(FontWeight.Medium)
    .margin({ bottom: 15 })

  ForEach(this.product.specs, (spec) => {
    Column() {
      Text(spec.name)
        .fontSize(14)
        .fontColor('#666666')
        .margin({ bottom: 10 })

      Flex({ wrap: FlexWrap.Wrap }) {
        ForEach(spec.options, (option) => {
          Text(option)
            .fontSize(14)
            .padding(10)
            .backgroundColor(this.selectedSpecs[spec.name] === option ? '#FFE4E4' : '#F5F5F5')
            .fontColor(this.selectedSpecs[spec.name] === option ? '#FF0000' : '#333333')
            .borderRadius(5)
            .margin({ right: 10, bottom: 10 })
            .onClick(() => {
              this.selectedSpecs[spec.name] = option
            })
        })
      }
    }
    .margin({ bottom: 20 })
  })
}
.width('100%')
.padding(15)
.backgroundColor(Color.White)
.margin({ top: 10 })
  1. 标题区域

    • 使用Text组件显示"规格选择"标题
    • 字体大小16,中等粗细,底部外边距15像素
  2. 规格项循环

    • 使用ForEach循环遍历product.specs数组
    • 为每个规格创建一个Column容器
  3. 规格名称

    • 显示规格名称(如"颜色"、"尺寸")
    • 字体大小14,颜色为深灰色(#666666),底部外边距10像素
  4. 规格选项布局

    • 使用Flex组件实现流式布局,设置wrap: FlexWrap.Wrap使选项可以自动换行
    • 当选项过多时,会自动换行显示,避免溢出屏幕
  5. 规格选项样式

    • 使用Text组件显示每个选项
    • 内边距10像素,圆角5像素
    • 右侧和底部外边距10像素,确保选项之间有适当间距

交互实现

Text(option)
  .fontSize(14)
  .padding(10)
  .backgroundColor(this.selectedSpecs[spec.name] === option ? '#FFE4E4' : '#F5F5F5')
  .fontColor(this.selectedSpecs[spec.name] === option ? '#FF0000' : '#333333')
  .borderRadius(5)
  .margin({ right: 10, bottom: 10 })
  .onClick(() => {
    this.selectedSpecs[spec.name] = option
  })
  1. 点击事件处理

    • 使用.onClick()方法为每个选项添加点击事件
    • 当用户点击选项时,更新selectedSpecs对象,将当前规格名称作为键,选中的选项作为值
  2. 动态样式变化

    • 背景色:选中时为浅红色(#FFE4E4),未选中时为浅灰色(#F5F5F5)
    • 文字颜色:选中时为红色(#FF0000),未选中时为深灰色(#333333)
    • 使用三元运算符根据选中状态动态切换样式
  3. 状态判断逻辑

    • this.selectedSpecs[spec.name] === option:判断当前选项是否被选中
    • 通过比较selectedSpecs对象中存储的值与当前选项是否相同来确定

总结

本篇文章详细讲解了如何使用HarmonyOS NEXT的Column和Flex组件构建商品详情页的规格选择区。通过合理的数据结构设计和组件嵌套,我们实现了规格选项的动态渲染和交互效果。

关键实现点:

  1. 数据结构设计:使用嵌套数组存储规格信息,使用Record对象存储选中状态
  2. 流式布局:使用Flex组件的FlexWrap.Wrap属性实现规格选项的自动换行
  3. 动态样式:根据选中状态动态切换背景色和文字颜色
  4. 事件处理:通过onClick事件更新选中状态

这种实现方式具有以下优势:

  1. 灵活性:可以轻松适应不同数量和类型的规格选项
  2. 可维护性:数据与UI分离,便于后期维护和扩展
  3. 用户体验:清晰的视觉反馈,帮助用户了解当前选择状态
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐