HarmonyOS ArkTS 数组操作与条件渲染实战
一、购物车商品展示与交互实现
在构建类似美团的商品详情页时,需要处理商品信息展示、价格计算以及用户对购买数量的操作。通过状态变量控制数据变化,并结合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')
}
}