#跟着若城学鸿蒙# HarmonyOS NEXT学习之SpanStepper案例二:购物流程实现
·
一、案例介绍
本案例将展示如何使用SpanStepper组件实现一个购物流程的分步操作界面,包括购物车确认、收货地址选择、支付方式选择等步骤。
二、代码实现
@Entry
@Component
struct ShoppingStepperExample {
@State currentStep: number = 0
@State cartItems: Array<{
name: string,
price: number,
quantity: number
}> = [
{ name: '商品1', price: 99.9, quantity: 1 },
{ name: '商品2', price: 199.9, quantity: 2 }
]
@State selectedAddress: string = ''
@State paymentMethod: string = ''
// 计算总价
getTotalPrice(): number {
return this.cartItems.reduce((total, item) => {
return total + (item.price * item.quantity)
}, 0)
}
build() {
Column() {
// 步骤指示器
SpanStepper() {
StepperItem() {
Column() {
Text('购物车确认').fontSize(16).fontWeight(FontWeight.Bold)
Text('确认商品和数量').fontSize(14).opacity(0.6)
}
}
.status(this.currentStep === 0 ? ItemState.CURRENT :
this.currentStep > 0 ? ItemState.COMPLETED : ItemState.WAITING)
StepperItem() {
Column() {
Text('收货地址').fontSize(16).fontWeight(FontWeight.Bold)
Text('选择收货地址').fontSize(14).opacity(0.6)
}
}
.status(this.currentStep === 1 ? ItemState.CURRENT :
this.currentStep > 1 ? ItemState.COMPLETED : ItemState.WAITING)
StepperItem() {
Column() {
Text('支付方式').fontSize(16).fontWeight(FontWeight.Bold)
Text('选择支付方式').fontSize(14).opacity(0.6)
}
}
.status(this.currentStep === 2 ? ItemState.CURRENT : ItemState.WAITING)
}
.width('100%')
.padding(16)
// 表单内容
Column() {
if (this.currentStep === 0) {
// 购物车商品列表
List() {
ForEach(this.cartItems, (item) => {
ListItem() {
Row() {
Text(item.name)
.fontSize(16)
Column() {
Text(`¥${item.price.toFixed(2)}`)
.fontSize(14)
Text(`数量:${item.quantity}`)
.fontSize(14)
.margin({ top: 4 })
}.alignItems(HorizontalAlign.End)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(8)
}
})
}
.width('100%')
// 总价
Text(`总计:¥${this.getTotalPrice().toFixed(2)}`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ top: 16 })
} else if (this.currentStep === 1) {
// 地址选择
Column() {
Radio({ value: 'address1', group: 'address' })
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedAddress = '地址1:北京市海淀区XX街道XX号'
}
})
Text('北京市海淀区XX街道XX号')
.fontSize(14)
.margin({ left: 8 })
}.margin({ top: 16 })
Column() {
Radio({ value: 'address2', group: 'address' })
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedAddress = '地址2:上海市浦东新区XX路XX号'
}
})
Text('上海市浦东新区XX路XX号')
.fontSize(14)
.margin({ left: 8 })
}.margin({ top: 16 })
} else {
// 支付方式选择
Column() {
Radio({ value: 'alipay', group: 'payment' })
.onChange((isChecked: boolean) => {
if (isChecked) {
this.paymentMethod = '支付宝'
}
})
Text('支付宝支付')
.fontSize(14)
.margin({ left: 8 })
}.margin({ top: 16 })
Column() {
Radio({ value: 'wechat', group: 'payment' })
.onChange((isChecked: boolean) => {
if (isChecked) {
this.paymentMethod = '微信支付'
}
})
Text('微信支付')
.fontSize(14)
.margin({ left: 8 })
}.margin({ top: 16 })
// 订单信息确认
Column() {
Text('订单信息确认').fontSize(16).fontWeight(FontWeight.Bold)
Text(`总金额:¥${this.getTotalPrice().toFixed(2)}`)
.margin({ top: 8 })
Text(`收货地址:${this.selectedAddress}`)
.margin({ top: 8 })
Text(`支付方式:${this.paymentMethod}`)
.margin({ top: 8 })
}
.width('100%')
.padding(16)
.margin({ top: 20 })
}
}.width('100%').padding({ left: 16, right: 16 })
// 操作按钮
Row() {
Button('上一步')
.enabled(this.currentStep > 0)
.opacity(this.currentStep > 0 ? 1 : 0.5)
.onClick(() => {
if (this.currentStep > 0) {
this.currentStep--
}
})
Button(this.currentStep === 2 ? '提交订单' : '下一步')
.enabled(this.currentStep < 3)
.onClick(() => {
if (this.currentStep < 2) {
this.currentStep++
} else {
// 在实际应用中,这里可以处理订单提交逻辑
console.info('订单提交成功')
}
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.padding(16)
.margin({ top: 20 })
}
}
}
三、代码解析
1. 状态定义
@State currentStep: number = 0 // 当前步骤索引
@State cartItems: Array<{ // 购物车商品列表
name: string,
price: number,
quantity: number
}>
@State selectedAddress: string = '' // 选择的收货地址
@State paymentMethod: string = '' // 选择的支付方式
- 使用
@State
装饰器定义组件的状态变量 cartItems
数组存储购物车商品信息selectedAddress
和paymentMethod
记录用户选择
2. 商品列表渲染
List() {
ForEach(this.cartItems, (item) => {
ListItem() {
Row() {
Text(item.name)
Column() {
Text(`¥${item.price.toFixed(2)}`)
Text(`数量:${item.quantity}`)
}
}
}
})
}
- 使用
List
和ForEach
组件循环渲染商品列表 - 展示商品名称、价格和数量信息
- 使用
toFixed(2)
格式化价格显示
3. 地址和支付方式选择
Radio({ value: 'address1', group: 'address' })
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedAddress = '地址1:北京市海淀区XX街道XX号'
}
})
- 使用
Radio
组件实现单选功能 - 通过
onChange
事件更新选择状态 - 使用
group
属性分组单选按钮
4. 订单信息确认
Column() {
Text('订单信息确认')
Text(`总金额:¥${this.getTotalPrice().toFixed(2)}`)
Text(`收货地址:${this.selectedAddress}`)
Text(`支付方式:${this.paymentMethod}`)
}
- 在最后一步显示订单汇总信息
- 展示总金额、收货地址和支付方式
- 使用模板字符串格式化显示内容
四、总结
通过本案例,我们学习了:
- SpanStepper组件在购物流程中的应用
- 如何实现商品列表的渲染和总价计算
- 使用Radio组件实现选择功能
- 订单信息的收集和展示
这些知识点将帮助你在实际项目中实现更复杂的购物流程界面。
更多推荐
所有评论(0)