当前位置:首页 > 技术 > 正文内容

HarmonyOS ArkTS 数组操作与条件渲染实战

访客 技术 2026年7月14日 2

一、购物车商品展示与交互实现

在构建类似美团的商品详情页时,需要处理商品信息展示、价格计算以及用户对购买数量的操作。通过状态变量控制数据变化,并结合UI更新实现动态响应。

@Entry
@Component
struct ProductDetail {
  @State quantity: number = 1
  @State currentPrice: number = 20.2
  @State originalPrice: number = 40.4

  build() {
    Column() {
      // 商品信息区域
      Row({ space: 10 }) {
        Image($r('app.media.product1'))
          .width(100)
          .borderRadius(8)

        Column({ space: 10 }) {
          Column({ space: 6 }) {
            Text('冲销量1000ml缤纷八果水果捞')
              .lineHeight(20)
              .fontSize(14)
            Text('含1份折扣商品')
              .fontSize(12)
              .fontColor('#7f7f7f')
          }
          .width('100%')
          .alignItems(HorizontalAlign.Start)

          Row() {
            // 价格显示
            Row({ space: 5 }) {
              Text(`¥${this.currentPrice}`)
                .fontSize(18)
                .fontColor('#ff4000')
              Text(`¥${this.originalPrice}`)
                .fontSize(14)
                .fontColor('#999')
                .decoration({
                  type: TextDecorationType.LineThrough,
                  color: '#999'
                })
            }

            // 数量增减控件
            Row() {
              Text('-')
                .width(22)
                .height(22)
                .border({ width: 1, color: '#e1e1e1', radius: { topLeft: 5, bottomLeft: 5 } })
                .textAlign(TextAlign.Center)
                .fontWeight(FontWeight.Bold)
                .onClick(() => {
                  if (this.quantity > 0) {
                    this.quantity--
                  } else {
                    AlertDialog.show({ message: '购物车已清空' })
                  }
                })

              Text(this.quantity.toString())
                .height(22)
                .width(30)
                .border({ width: { top: 1, bottom: 1 }, color: '#e1e1e1' })
                .padding({ left: 10, right: 10 })
                .fontSize(14)

              Text('+')
                .width(22)
                .height(22)
                .border({ width: 1, color: '#e1e1e1', radius: { topRight: 5, bottomRight: 5 } })
                .textAlign(TextAlign.Center)
                .fontWeight(FontWeight.Bold)
                .onClick(() => {
                  this.quantity++
                })
            }
          }
          .width('100%')
          .justifyContent(FlexAlign.SpaceBetween)
        }
        .layoutWeight(1)
        .height(75)
        .justifyContent(FlexAlign.SpaceBetween)
      }
      .width('100%')
      .alignItems(VerticalAlign.Top)
      .padding(20)

      // 结算栏
      Row({ space: 10 }) {
        Column({ space: 5 }) {
          Text(`已选${this.quantity}件,合计: ¥${(this.quantity * this.currentPrice).toFixed(2)}`)
            .fontSize(14)
            .children([
              Span(`共减¥${((this.originalPrice - this.currentPrice) * this.quantity).toFixed(2)}`)
                .fontColor('#fd4104')
                .fontSize(12)
            ])
        }
        .alignItems(HorizontalAlign.End)

        Button('结算外卖')
          .width(110)
          .height(40)
          .backgroundColor('#fed70e')
          .fontColor('#564200')
          .fontSize(16)
          .fontWeight(600)
      }
      .width('100%')
      .height(70)
      .backgroundColor('#fff')
      .position({ x: 0, y: '100%' })
      .translate({ y: '-100%' })
      .padding({ left: 20, right: 20 })
      .justifyContent(FlexAlign.End)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#f3f3f3')
  }
}

二、数组的基本操作方法

在前端开发中,常需对列表数据进行增删改查。ArkTS 支持标准 TypeScript 的数组操作方式。

1. 添加元素

  • unshift():在数组开头插入一个或多个元素,返回新长度。
  • push():在末尾添加元素,返回新的数组长度。
let userList: string[] = ['Tom', 'Jack', 'Jerry']
console.log(userList.unshift('Rose')) // 输出: 4
console.log(userList) // ['Rose', 'Tom', 'Jack', 'Jerry']

console.log(userList.push('Lisa')) // 输出: 5
console.log(userList) // ['Rose', 'Tom', 'Jack', 'Jerry', 'Lisa']

2. 删除元素

  • shift():移除第一个元素并返回该值。
  • pop():删除最后一个元素并返回其值。
console.log(userList.shift()) // 'Rose'
console.log(userList) // ['Tom', 'Jack', 'Jerry', 'Lisa']

console.log(userList.pop()) // 'Lisa'
console.log(userList) // ['Tom', 'Jack', 'Jerry']

3. 任意位置修改 splice()

使用 splice(startIndex, deleteCount, item1, item2, ...) 可以从指定索引开始删除若干项,并可同时插入新元素。

userList.splice(1, 2, 'Emma', 'Noah') 
// 从索引1开始删除2个元素,插入'Emma'和'Noah'
console.log(userList) // ['Tom', 'Emma', 'Noah']

三、条件判断语句的应用

根据不同的业务逻辑条件渲染不同内容是 UI 开发中的常见需求。

if-else 分支结构

适用于范围判断场景,如成绩等级划分、年龄权限控制等。

let age: number = 16
if (age >= 18) {
  console.log('允许进入')
} else {
  console.log('禁止进入')
}

let score: number = 75
if (score >= 90) {
  AlertDialog.show({ message: '优秀' })
} else if (score >= 70) {
  AlertDialog.show({ message: '良好' })
} else if (score >= 60) {
  AlertDialog.show({ message: '及格' })
} else {
  AlertDialog.show({ message: '不及格' })
}

switch-case 精确匹配

适合用于等值判断,避免多重 if 带来的冗余比较。

let fruit: string = '橘子'
switch (fruit) {
  case '苹果':
    console.log('苹果5元/斤')
    break
  case '橘子':
    console.log('橘子3元/斤')
    break
  default:
    console.log('该水果已售罄')
}

四、三元运算符实现动态渲染

三元表达式简洁地实现基于布尔状态的文本或样式切换。

let a: number = 5
let b: number = 10
let max: number = a > b ? a : b
console.log('较大值为:', max)

案例:关注按钮切换

利用三元运算动态改变按钮文字和背景色。

@Entry
@Component
struct FollowButtonExample {
  @State isFollowed: boolean = false

  build() {
    Column() {
      Button(this.isFollowed ? '已关注' : '+ 关注')
        .backgroundColor(this.isFollowed ? Color.Orange : Color.Blue)
        .onClick(() => {
          this.isFollowed = !this.isFollowed
        })
    }
    .width('100%')
    .height('100%')
  }
}

五、电商加购功能完整示例

结合条件渲染实现库存提示与操作按钮切换。

@Entry
@Component
struct ShoppingFooter {
  @State cartCount: number = 0
  @State bannerOpacity: number = 1

  build() {
    Column() {
      Column() {
        // 底部操作栏
        Row({ space: 10 }) {
          // 左侧图标菜单
          Row() {
            Column({ space: 5 }) {
              Image($r('app.media.ic_dianpu')).width(20)
              Text('店铺').fontSize(10).fontColor('#262626')
            }
            Column({ space: 5 }) {
              Image($r('app.media.ic_kefu')).width(20).fillColor('#666')
              Text('客服').fontSize(10).fontColor('#262626')
            }
            Column({ space: 5 }) {
              Image($r('app.media.ic_cart2')).width(20).fillColor('#666')
              Text('购物车').fontSize(10).fontColor('#262626')
            }
          }
          .layoutWeight(1)
          .justifyContent(FlexAlign.SpaceBetween)

          // 右侧购买按钮组
          if (this.cartCount > 0) {
            Row({ space: 5 }) {
              Button('加入购物车')
                .width(105)
                .height(40)
                .backgroundColor('#ffcc00')
                .fontSize(14)
                .fontWeight(600)
              Button('立即购买')
                .width(105)
                .height(40)
                .backgroundColor('#f92c1b')
                .fontSize(14)
                .fontWeight(600)
            }
          } else {
            Row() {
              Button('查看类似商品')
                .width(170)
                .height(40)
                .backgroundColor('#ffcc00')
                .fontSize(14)
                .fontWeight(600)
            }
          }
        }
        .width('100%')
        .height(60)
        .backgroundColor('#f7f7f7')
        .padding({ left: 20, right: 10 })

        // 库存提醒横幅
        if (this.cartCount <= 0) {
          Row() {
            Row({ space: 5 }) {
              Image($r('app.media.ic_lingdang'))
                .width(12)
                .fillColor('#de6a1c')
              Text('该商品暂时无货,可浏览推荐商品')
                .fontSize(10)
                .fontColor('#de6a1c')
            }
            Image($r('app.media.ic_close'))
              .width(15)
              .padding(3)
              .fillColor('#d0662c')
              .backgroundColor('rgba(0,0,0,0.1)')
              .borderRadius(8)
              .onClick(() => {
                this.bannerOpacity = 0
              })
          }
          .width('100%')
          .height(36)
          .backgroundColor('#fbf9da')
          .position({ x: 0, y: '-36' })
          .padding({ left: 20, right: 20 })
          .justifyContent(FlexAlign.SpaceBetween)
          .opacity(this.bannerOpacity)
        }
      }
      .position({ x: 0, y: '100%' })
      .translate({ y: '-100%' })
    }
    .width('100%')
    .height('100%')
    .padding({ bottom: 20 })
    .backgroundColor('#f2f2f2')
  }
}
标签: ArkTSHarmonyOS

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。