HarmonyOS Next 之购物车功能开发实战

2025-06-18 14:38:48
108次阅读
0个评论

本系列教程将详细讲解如何基于 HarmonyOS Next 和 ArkUI 框架实现完整的购物车功能,涵盖核心交互场景与高级特性。以下是各模块的实现方案:

1 商品列表展示与基础布局

功能说明

实现商品卡片式布局,包含图片、标题、价格和数量选择器。

代码实现

// CartItem.ets
@Component
export struct CartItem {
  private item: CartItemData; // 商品数据对象
  @Link @Watch('onCountChange') count: number;

  // 数量变化监听
  onCountChange() {
    console.info(`商品 ${this.item.name} 数量更新为:${this.count}`);
  }

  build() {
    Row() {
      Image(this.item.image) // 商品图片
        .width(80)
        .height(80)
        .borderRadius(8)

      Column() {
        Text(this.item.name) // 商品名称
          .fontSize(18)
          .fontColor(Color.Black)
        Text(`¥${this.item.price}`) // 商品价格
          .fontSize(16)
          .fontColor('#FF5722')
      }
      .layoutWeight(1)
      .margin({ left: 12 })

      // 数量增减按钮
      CounterComponent({ count: $count })
    }
    .padding(12)
    .backgroundColor(Color.White)
    .margin({ bottom: 8 })
    .borderRadius(8)
  }
}

// CounterComponent.ets(数量选择子组件)
@Component
struct CounterComponent {
  @Link count: number;

  build() {
    Row() {
      Button('-')
        .onClick(() => this.count > 1 && this.count--)
      Text(this.count.toString())
        .margin({ left: 8, right: 8 })
      Button('+')
        .onClick(() => this.count++)
    }
  }
}

2 全选/反选与批量操作

功能说明

实现全选复选框、批量删除和实时总价计算。

代码实现

// CartPage.ets
@Entry
@Component
struct CartPage {
  @State cartItems: CartItemData[] = [/* 初始数据 */];
  @State isAllSelected: boolean = false;

  // 计算总价
  get totalPrice(): number {
    return this.cartItems
      .filter(item => item.selected)
      .reduce((sum, item) => sum + item.price * item.count, 0);
  }

  // 全选/反选
  toggleAllSelection() {
    this.isAllSelected = !this.isAllSelected;
    this.cartItems = this.cartItems.map(item => ({
      ...item,
      selected: this.isAllSelected
    }));
  }

  build() {
    Column() {
      // 全选操作栏
      Row() {
        Checkbox({ value: this.isAllSelected })
          .onChange(() => this.toggleAllSelection())
        Text('全选')
        Button('删除选中')
          .onClick(() => {
            this.cartItems = this.cartItems.filter(item => !item.selected)
          })
      }

      // 商品列表
      List({ space: 12 }) {
        ForEach(this.cartItems, (item) => {
          ListItem() {
            CartItem({ item: item, count: $item.count })
              .onClick(() => item.selected = !item.selected)
          }
        })
      }
      .layoutWeight(1)

      // 底部结算栏
      Row() {
        Text(`合计:¥${this.totalPrice.toFixed(2)}`)
          .fontSize(20)
          .fontColor('#FF5722')
        Button('去结算')
          .backgroundColor('#07C160')
          .width(120)
      }
      .padding(16)
    }
  }
}

3 删除商品动画

功能说明

实现左滑删除动画与物理震动反馈。

代码实现

// SwipeToDelete.ets
@Component
struct SwipeToDelete {
  @State translateX: number = 0;
  @State isDeleting: boolean = false;

  build() {
    Stack() {
      // 删除按钮背景
      Row() {
        Button($r('app.media.ic_delete'))
          .onClick(() => this.isDeleting = true)
      }
      .width(80)
      .height('100%')
      .justifyContent(FlexAlign.End)
      .backgroundColor('#FF3B30')
      .opacity(this.translateX < -20 ? 1 : 0)

      // 商品项主内容
      Row() {
        CartItem({ /* 商品数据 */ })
      }
      .translate({ x: this.translateX })
      .gesture(
        PanGesture({ distance: 5 })
          .onActionUpdate((event: GestureEvent) => {
            if (Math.abs(event.offsetX) > 20) {
              this.translateX = event.offsetX;
            }
          })
          .onActionEnd(() => {
            if (this.translateX < -60) {
              animateTo({ duration: 200 }, () => {
                this.translateX = -200;
                this.isDeleting = true;
              })
            } else {
              animateTo({ duration: 200 }, () => this.translateX = 0)
            }
          })
      )
    }
    .height(100)
    .clip(true)
  }
}

4 数据持久化存储

功能说明

使用 @ohos.data.storage 实现购物车本地缓存。

代码实现

// CartStorage.ets
import { storage } from '@ohos.data.storage';

const STORAGE_KEY = 'cartData';

export class CartStorage {
  static async saveCart(items: CartItemData[]) {
    const storage = await storage.getStorage();
    await storage.set(STORAGE_KEY, JSON.stringify(items));
    await storage.flush();
  }

  static async loadCart(): Promise<CartItemData[]> {
    const storage = await storage.getStorage();
    const data = await storage.get(STORAGE_KEY, '[]');
    return JSON.parse(data);
  }
}

// 在页面中调用
aboutToAppear() {
  CartStorage.loadCart().then(items => this.cartItems = items);
}

aboutToDisappear() {
  CartStorage.saveCart(this.cartItems);
}
  • 依赖项:
"dependencies": {
  "@ohos.data.storage": ">=3.1.0",
  "@ohos.vibrator": ">=3.1.0" // 震动反馈模块
}
  • 权限申请:
"requestPermissions": [
  { "name": "ohos.permission.VIBRATE" }
]
收藏00

登录 后评论。没有帐号? 注册 一个。