赞
踩
在utils
目录下新建CartStore.ets
文件,如下:
import { FoodItem } from '../models' // 本地持久化购物车数据 PersistentStorage.persistProp<FoodItem[]>('cartStore', []) export class CartStore { static getCarts() { return AppStorage.get<FoodItem[]>('cartStore') || [] as FoodItem[] } /** * 加菜or减菜 * @param foodItem * @param type */ static addOrCutFood(foodItem: FoodItem, type: 'add' | 'cut') { const cartList = CartStore.getCarts() const item = cartList.find((item) => item.id === foodItem.id) // 加菜 if (type === 'add') { if (item) { item.count++ } else { foodItem.count = 1 cartList.unshift(foodItem) } } else { // 减菜 if (item && item.count > 0) { item.count-- if (item.count === 0) { const index = cartList.findIndex((item) => item.id === foodItem.id) cartList.splice(index, 1) } } } AppStorage.set<FoodItem[]>('cartStore', [...cartList]) } }
实现如下效果,当选择数量大于0时展示-及数量
:
改造MTAddCutView
,如下:
import { FoodItem } from '../models' import { CartStore } from '../utils/CartStore' @Preview @Component export struct MTAddCutView { // 当前菜品 @Require @Prop foodItem: FoodItem = new FoodItem() // 购物车数据 @Consume cartList: FoodItem[] // 当前选择数量 getCount() { return this.cartList.find(obj => obj.id === this.foodItem.id)?.count || 0 } build() { Row({ space: 8 }) { Row() { Image($r('app.media.ic_screenshot_line')) .width(10) .aspectRatio(1) } .width(16) .height(16) .justifyContent(FlexAlign.Center) .backgroundColor(Color.White) .borderRadius(4) .border({ color: $r('app.color.main_color'), width: 0.5 }) // 如果为0,则取消展示 .visibility(this.getCount() > 0 ? Visibility.Visible : Visibility.Hidden) // 减少菜品 .onClick(() => { CartStore.addOrCutFood(this.foodItem, 'cut') }) Text(this.getCount().toString()) .fontSize(14) .visibility(this.getCount() > 0 ? Visibility.Visible : Visibility.Hidden) Row() { Image($r('app.media.ic_public_add_filled')) .width(10) .aspectRatio(1) } .width(16) .height(16) .justifyContent(FlexAlign.Center) .borderRadius(4) .backgroundColor($r('app.color.main_color')) // 添加菜品 .onClick(() => { CartStore.addOrCutFood(this.foodItem, 'add') }) } } }
在主页面MeiTuanPage.ets
中,通过Watch
和StorageProp
实现数据动态展示:
// 方案一:使用StorageProp和Watch实现
@StorageProp('cartStore') @Watch('onCartChange') cartData: FoodItem[] = []
// 购物车数据变化发生回调
onCartChange() {
this.cartList = CartStore.getCarts()
}
使用事件总线实现事件的发布和订阅。
在CartStore.ets
中增加事件发布:
...
AppStorage.set<FoodItem[]>('cartStore', [...cartList])
// 方案二:使用事件总线
getContext().eventHub.emit('changeCart')
...
在MeiTuanPage.ets
中注册订阅:
aboutToAppear(): void {
this.categoryList = mockCategory
this.cartList = CartStore.getCarts()
// 方案二:使用事件总线
getContext().eventHub.on('changeCart', () => {
this.cartList = CartStore.getCarts()
})
}
购物车展示真实数据及加减菜品:
MTCartView
import { FoodItem } from '../models' import { MTCartItemView } from './MTCartItemView' @Preview @Component export struct MTCartView { @Consume cartList: FoodItem[] build() { Column() { Column() { // 头部 Row() { Text('购物车') .fontSize(14) Text('清空购物车') .fontColor($r('app.color.search_font_color')) .fontSize(12) } .width('100%') .height(48) .justifyContent(FlexAlign.SpaceBetween) .padding({ left: 15, right: 15 }) // 购物车列表 List() { ForEach(this.cartList, (item: FoodItem) => { ListItem() { MTCartItemView({ foodItem: item }) } }) } .divider({ strokeWidth: 1, color: '#e5e5e5', startMargin: 20, endMargin: 20 }) } .backgroundColor(Color.White) .padding({ bottom: 88 }) .borderRadius({ topLeft: 12, topRight: 12 }) } .width('100%') .height('100%') .justifyContent(FlexAlign.End) .backgroundColor('rgba(0,0,0,0.5)') } }
MTCartItemView
import { FoodItem } from '../models' import { MTAddCutView } from './MTAddCutView' @Preview @Component export struct MTCartItemView { foodItem: FoodItem = new FoodItem() build() { Row({ space: 6 }) { Image('https://bkimg.cdn.bcebos.com/pic/4d086e061d950a7bc94a331704d162d9f3d3c9e2') .width(42) .aspectRatio(1) .borderRadius(5) Column({ space: 3 }) { Text(this.foodItem.name) Row() { Text() { Span('¥') .fontSize(10) Span(this.foodItem.price.toString()) .fontColor($r('app.color.main_color')) .fontSize(14) .fontWeight(600) } MTAddCutView({ foodItem: this.foodItem }) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) } .layoutWeight(1) .alignItems(HorizontalAlign.Start) } .height(60) .alignItems(VerticalAlign.Top) .width('100%') .padding({ top: 12, left: 15, right: 15, bottom: 12 }) } }
CartStore.ets
中增加清空方法:
static clearCart() {
AppStorage.set('cartStore', [])
getContext().eventHub.emit('changeCart')
}
购物车View中增加点击事件:
...
Text('清空购物车')
.fontColor($r('app.color.search_font_color'))
.fontSize(12)
.onClick(() => {
CartStore.clearCart()
})
...
修改MTBottomView
,计算购物车数量和价格:
import { FoodItem } from '../models' @Component export struct MTBottomView { @Consume showCart: boolean @Consume cartList: FoodItem[] // 获取总数量 getTotalCount() { return this.cartList.reduce((pre: number, item: FoodItem) => { return pre + item.count }, 0) } // 获取总价格 getTotalPrice() { return this.cartList.reduce((pre: number, item: FoodItem) => { return pre + item.count * item.price }, 0) } build() { Row() { // 小哥+角标 Badge({ value: this.getTotalCount().toString(), style: { badgeSize: 18 }, position: BadgePosition.Right }) { Image($r('app.media.ic_public_cart')) .height(69) .width(47) .position({ y: -20 }) } .margin({ left: 28, right: 12 }) .onClick(() => { this.showCart = !this.showCart }) // 金额+描述 Column() { Text() { Span('¥') .fontColor(Color.White) .fontSize(12) Span(this.getTotalPrice().toString()) .fontColor(Color.White) .fontSize(25) } Text('预估另需配送费¥5') .fontColor($r('app.color.search_font_color')) .fontSize(12) } .alignItems(HorizontalAlign.Start) .layoutWeight(1) // 去结算 Text('去结算') .width(80) .height(50) .fontSize(16) .backgroundColor($r('app.color.main_color')) .textAlign(TextAlign.Center) .borderRadius({ topRight: 25, bottomRight: 25 }) } .height(50) .width('88%') .margin({ bottom: 20 }) .backgroundColor(Color.Black) .borderRadius(26) } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。