HarmonyOS鸿蒙Next中请教怎么简化这个函数?

HarmonyOS鸿蒙Next中请教怎么简化这个函数?

@Builder
MyText(name: string, tnum: MENUTYPE) {
  if (tnum == MENUTYPE.ESHUCAI) {
    Text(name + '(' + this.m_countShuCai + ')')
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({
        left: 12,
        right: 12,
        top: 8,
        bottom: 8
      })
      .borderRadius(20)
  }

  if (tnum == MENUTYPE.EROU) {
    Text(name + '(' + this.m_countRou + ')')
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({
        left: 12,
        right: 12,
        top: 8,
        bottom: 8
      })
      .borderRadius(20)
  }

  if (tnum == MENUTYPE.EWUGU) {
    Text(name + '(' + this.m_countWuGu + ')')
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({
        left: 12,
        right: 12,
        top: 8,
        bottom: 8
      })
      .borderRadius(20)
  }

  if (tnum == MENUTYPE.ETIAOLIAO) {
    Text(name + '(' + this.m_countTiaoLiao + ')')
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({
        left: 12,
        right: 12,
        top: 8,
        bottom: 8
      })
      .borderRadius(20)
  }
}

更多关于HarmonyOS鸿蒙Next中请教怎么简化这个函数?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

13 回复

根据给的demo,楼主的想法应该是想各自统计不同类别的数量。
优化方式如下:

class Tmp5 {
  public name: string = '';
  public count: number = 0;
}

@Component
export struct TestPage{
  @State m_countShuCai: number = 0
  @State m_countRou: number = 0
  @State m_countWuGu: number = 0
  @State m_countTiaoLiao: number = 0

  @Builder
  MyText(params: Tmp5) {
    Text(params.name + '(' + params.count + ')')
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({
        left: 12,
        right: 12,
        top: 8,
        bottom: 8
      })
      .borderRadius(20)
  }

  build() {
    Column(){
      this.MyText({name: '蔬菜', count: this.m_countShuCai})
      this.MyText({name: '肉', count: this.m_countRou})
      this.MyText({name: '五谷', count: this.m_countWuGu})
      this.MyText({name: '调料', count: this.m_countTiaoLiao})
      Text('点击按钮').margin({top: 20}).onClick(() => {
        this.m_countShuCai = this.m_countShuCai + 1
        this.m_countRou += 1
      })
    }
  }
}

更多关于HarmonyOS鸿蒙Next中请教怎么简化这个函数?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


的确,加了。几周不写就漏了。。。

这样穿的不是引用,界面更新不了吧

问题点:count重复太多、维护成本高。

优化点:先算出 count,再只写一份 Text 样式。

示例代码:

@Builder
MyText(name: string, tnum: MENUTYPE) {
  let count: number = 0
  if (tnum === MENUTYPE.ESHUCAI) {
    count = this.m_countShuCai
  } else if (tnum === MENUTYPE.EROU) {
    count = this.m_countRou
  } else if (tnum === MENUTYPE.EWUGU) {
    count = this.m_countWuGu
  } else if (tnum === MENUTYPE.ETIAOLIAO) {
    count = this.m_countTiaoLiao
  }

  Text(name + '(' + count + ')')
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({
      left: 12,
      right: 12,
      top: 8,
      bottom: 8
    })
    .borderRadius(20)
}

m_countXXX都是@state,需要界面更新

根据提供的信息,主要做以下优化,核心优化思路:

  • 提取公共样式 - 使用 @Builder 的参数传递机制
  • 使用映射关系 - 将 MENUTYPE 与对应的 count 值建立映射
  • 按引用传递 - 确保 @State 变量变化能触发 UI 更新

以下是Demo示例:

// 定义菜单类型枚举 - 添加前缀避免冲突
enum FoodMenuType {
  VEGETABLE = 0,  // 蔬菜
  MEAT = 1,       // 肉类
  GRAIN = 2,      // 五谷
  CONDIMENT = 3   // 调料
}

// 菜单项数据接口 - 添加前缀
interface FoodMenuItem {
  name: string;
  type: FoodMenuType;
  icon: string;
}

@Entry
@Component
struct MenuDemo {
  // 各类食材数量 - 使用 [@State](/user/State) 确保界面更新
  [@State](/user/State) m_countVegetable: number = 5;
  [@State](/user/State) m_countMeat: number = 3;
  [@State](/user/State) m_countGrain: number = 8;
  [@State](/user/State) m_countCondiment: number = 12;

  // 菜单数据
  private menuItems: FoodMenuItem[] = [
    { name: '蔬菜', type: FoodMenuType.VEGETABLE, icon: '🥬' },
    { name: '肉类', type: FoodMenuType.MEAT, icon: '🥩' },
    { name: '五谷', type: FoodMenuType.GRAIN, icon: '🌾' },
    { name: '调料', type: FoodMenuType.CONDIMENT, icon: '🧂' }
  ];

  // ==================== 优化后的 [@Builder](/user/Builder) ====================
  [@Builder](/user/Builder)
  MyTextOptimized(name: string, tnum: FoodMenuType) {
    Text(`${name}(${this.getCountByType(tnum)})`)
      .fontSize(16)
      .fontColor('#2E7D32')
      .backgroundColor('#00000000')
      .linearGradient({
        direction: GradientDirection.Bottom,
        colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
      })
      .padding({ left: 12, right: 12, top: 8, bottom: 8 })
      .borderRadius(20)
  }

  /**
   * 根据类型获取对应数量
   */
  private getCountByType(type: FoodMenuType): number {
    switch (type) {
      case FoodMenuType.VEGETABLE:
        return this.m_countVegetable;
      case FoodMenuType.MEAT:
        return this.m_countMeat;
      case FoodMenuType.GRAIN:
        return this.m_countGrain;
      case FoodMenuType.CONDIMENT:
        return this.m_countCondiment;
      default:
        return 0;
    }
  }

  build() {
    Column({ space: 20 }) {
      // 标题
      Text('食材分类统计')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      // 优化后的 Builder
      Text('通过 this 访问状态变量')
        .fontSize(14)
        .fontColor('#666666')

      Row({ space: 10 }) {
        ForEach(this.menuItems, (item: FoodMenuItem) => {
          this.MyTextOptimized(item.name, item.type)
        })
      }

      Divider().margin({ top: 10, bottom: 10 })

      // 操作按钮
      Text('操作面板')
        .fontSize(16)
        .fontWeight(FontWeight.Medium)

      Row({ space: 10 }) {
        Button('蔬菜+1')
          .onClick(() => { this.m_countVegetable++; })
          .backgroundColor('#4CAF50')

        Button('肉类+1')
          .onClick(() => { this.m_countMeat++; })
          .backgroundColor('#F44336')

        Button('五谷+1')
          .onClick(() => { this.m_countGrain++; })
          .backgroundColor('#FF9800')

        Button('调料+1')
          .onClick(() => { this.m_countCondiment++; })
          .backgroundColor('#9C27B0')
      }

      Row({ space: 10 }) {
        Button('蔬菜-1')
          .onClick(() => {
            if (this.m_countVegetable > 0) this.m_countVegetable--;
          })
          .backgroundColor('#81C784')

        Button('肉类-1')
          .onClick(() => {
            if (this.m_countMeat > 0) this.m_countMeat--;
          })
          .backgroundColor('#E57373')

        Button('五谷-1')
          .onClick(() => {
            if (this.m_countGrain > 0) this.m_countGrain--;
          })
          .backgroundColor('#FFB74D')

        Button('调料-1')
          .onClick(() => {
            if (this.m_countCondiment > 0) this.m_countCondiment--;
          })
          .backgroundColor('#BA68C8')
      }

      Button('重置所有')
        .onClick(() => {
          this.m_countVegetable = 5;
          this.m_countMeat = 3;
          this.m_countGrain = 8;
          this.m_countCondiment = 12;
        })
        .backgroundColor('#607D8B')
        .width('80%')
    }
    .width('100%')
    .padding(20)
    .backgroundColor('#F5F5F5')
  }
}

整体代码重复太多了吧,只有两个地方不一样。拼接的计数字段:m_countShuCai / m_countRou /…

枚举类型:MENUTYPE.xxx

简单改一下:

@Builder
MyText(name: string, tnum: MENUTYPE) {
  const count = {
    [MENUTYPE.ESHUCAI]: this.m_countShuCai,
    [MENUTYPE.EROU]: this.m_countRou,
    [MENUTYPE.EWUGU]: this.m_countWuGu,
    [MENUTYPE.ETIAOLIAO]: this.m_countTiaoLiao,
  }[tnum];

  count && Text(`${name}(${count})`)
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({ left: 12, right: 12, top: 8, bottom: 8 })
    .borderRadius(20);
}

2楼说的没毛病

思路走偏了!

如果你只是想给一个Text赋值,那么只需要定义一个m_count的变量去赋值就行了。而不是定义那么多个count。

方案一(简单直接):

@Builder
MyText(name: string, tnum: MENUTYPE) {
  Text(this.getDisplayText(name, tnum))
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({
      left: 12,
      right: 12,
      top: 8,
      bottom: 8
    })
    .borderRadius(20)
}

// 提取文本生成逻辑
private getDisplayText(name: string, tnum: MENUTYPE): string {
  let count = 0;
  switch (tnum) {
    case MENUTYPE.ESHUCAI:
      count = this.m_countShuCai;
      break;
    case MENUTYPE.EROU:
      count = this.m_countRou;
      break;
    case MENUTYPE.EWUGU:
      count = this.m_countWuGu;
      break;
    case MENUTYPE.ETIAOLIAO:
      count = this.m_countTiaoLiao;
      break;
  }
  return `${name}(${count})`;
}

方案二(映射表,更优雅):

// 定义计数映射
private countMap: Map<MENUTYPE, number> = new Map([
  [MENUTYPE.ESHUCAI, this.m_countShuCai],
  [MENUTYPE.EROU, this.m_countRou],
  [MENUTYPE.EWUGU, this.m_countWuGu],
  [MENUTYPE.ETIAOLIAO, this.m_countTiaoLiao]
]);

@Builder
MyText(name: string, tnum: MENUTYPE) {
  Text(`${name}(${this.countMap.get(tnum) || 0})`)
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({
      left: 12,
      right: 12,
      top: 8,
      bottom: 8
    })
    .borderRadius(20)
}

方案三(样式提取,适合多处复用):

// 定义计数映射
private countMap: Map<MENUTYPE, number> = new Map([
  [MENUTYPE.ESHUCAI, this.m_countShuCai],
  [MENUTYPE.EROU, this.m_countRou],
  [MENUTYPE.EWUGU, this.m_countWuGu],
  [MENUTYPE.ETIAOLIAO, this.m_countTiaoLiao]
]);

@Builder
MyText(name: string, tnum: MENUTYPE) {
  Text(`${name}(${this.countMap.get(tnum) || 0})`)
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({
      left: 12,
      right: 12,
      top: 8,
      bottom: 8
    })
    .borderRadius(20)
}

m_countXXX都是@state,需要界面更新

无法简化未知函数,请提供具体ArkTS代码。通常简化可通过提取公共逻辑、使用解构赋值、箭头函数或合并重复条件实现。

提取公共样式,用变量区分计数来源即可:

@Builder
MyText(name: string, tnum: MENUTYPE) {
  let count = 0
  switch(tnum) {
    case MENUTYPE.ESHUCAI: count = this.m_countShuCai; break;
    case MENUTYPE.EROU: count = this.m_countRou; break;
    case MENUTYPE.EWUGU: count = this.m_countWuGu; break;
    case MENUTYPE.ETIAOLIAO: count = this.m_countTiaoLiao; break;
  }
  Text(`${name}(${count})`)
    .fontSize(16)
    .fontColor('#2E7D32')
    .backgroundColor('#00000000')
    .linearGradient({
      direction: GradientDirection.Bottom,
      colors: [['#E8F5E9', 0.0], ['#C8E6C9', 1.0]]
    })
    .padding({ left: 12, right: 12, top: 8, bottom: 8 })
    .borderRadius(20)
}

四段重复逻辑合并为一段,仅通过switch获取对应计数值。

回到顶部