HarmonyOS5 购物商城app(一):商品展示(附代码)

2025-06-28 20:13:51
108次阅读
0个评论

image.png

基于ArkTS的电商应用架构设计

一、核心数据模型

1. 轮播图数据模型

class BannerClass {
  id: string;
  imagePath: string;
  title: string;

  constructor(id: string, imagePath: string, title: string) {
    this.id = id;
    this.imagePath = imagePath;
    this.title = title;
  }
}

2. 商品数据模型

class ShopClass {
  id: string;
  imagePath: string;
  title: string;
  price: string;

  constructor(id: string, imagePath: string, title: string, price: string) {
    this.id = id;
    this.imagePath = imagePath;
    this.title = title;
    this.price = price;
  }
}

二、页面架构设计

1. 首页组件结构

@Entry
@Component
struct Index {
  @Provide('mainStarIndex') mainStarIndex: NavPathStack = new NavPathStack();
  
  private SliderImage: BannerClass[] = [...];
  private TutorialArray: ShopClass[] = [...];
  
  build() {
    Navigation(this.mainStarIndex) {
      Column({ space: 15 }) {
        // 轮播图区域
        Swiper() { ... }
        
        // 商品瀑布流
        WaterFlow() {
          ForEach(this.TutorialArray, (item: ShopClass) => {
            FlowItem() {
              this.productCard(item) // 商品卡片组件
            }
          })
        }
      }
    }
  }
  
  @Builder
  productCard(item: ShopClass) { ... }
}

三、核心UI组件实现

1. 轮播图组件

Swiper() {
  ForEach(this.SliderImage, (item: BannerClass) => {
    Image($r(item.imagePath))
      .width('100%')
      .height(200)
      .objectFit(ImageFit.Cover)
      .borderRadius(20)
  })
}
.autoPlay(true)
.interval(3000)
.indicatorStyle({ color: '#ffffff' })

2. 商品卡片组件

@Builder
productCard(item: ShopClass) {
  Column({ space: 10 }) {
    Image($r(item.imagePath))
      .width('100%')
      .height(150)
      .borderRadius(12)
      .transition({ type: TransitionType.All, scale: { x: 0.95, y: 0.95 } })
    
    Text(item.title)
      .fontSize(18)
      .fontWeight(FontWeight.Bold)
    
    Row() {
      // 评分组件
      Row({ space: 5 }) {
        Image($r('app.media.star')).width(18)
        Text('4.5').fontColor('#666666')
      }
      
      // 价格组件
      Text(`¥${item.price}`)
        .fontColor('#e6393f')
        .fontWeight(FontWeight.Bold)
        .layoutWeight(1)
        .textAlign(TextAlign.End)
    }
  }
  .hoverEffect(HoverEffect.Scale)
  .shadow({ radius: 6 })
}

四、商品详情页实现

1. 页面结构

@Component
export struct ShopsView {
  @Consume('mainStarIndex') mainStarIndex: NavPathStack;
  @Prop article: ShopClass;
  
  build() {
    NavDestination() {
      Stack() {
        // 顶部轮播图
        this.productGallery()
        
        // 返回按钮
        this.backButton()
      }
      
      // 商品信息区域
      Column() {
        this.productInfo()
        this.serviceFeatures()
        this.addToCartButton()
      }
    }
  }
}

2. 商品图库组件

@Builder
productGallery() {
  Swiper() {
    ForEach(this.SliderArray, (item: BannerClass) => {
      Image($r(item.imagePath))
        .height(300)
        .transition({ opacity: 0.8, scale: { x: 0.95, y: 0.95 } })
    })
  }
  .autoPlay(true)
  .borderRadius(20)
}

3. 商品信息组件

@Builder
productInfo() {
  Column({ space: 15 }) {
    Text(this.article.title)
      .fontSize(26)
      .fontWeight(FontWeight.Bold)
    
    Row() {
      Text(`¥${this.article.price.split('¥')[1]}`)
        .fontColor('#e6393f')
      
      Text('已售 1000+')
        .fontColor('#999999')
    }
    
    Text('商品描述内容...')
      .lineHeight(26)
  }
}

五、导航与状态管理

1. 导航架构

@Provide('mainStarIndex') mainStarIndex: NavPathStack = new NavPathStack();

@Builder
shopPage(name: string, params: ShopClass | string) {
  if (name === 'shopCartView') {
    ShopsView({ article: params as ShopClass });
  }
}

// 页面跳转
this.mainStarIndex.pushPathByName('shopCartView', item);

2. 详情页数据接收

@Component
export struct ShopsView {
  @Consume('mainStarIndex') mainStarIndex: NavPathStack;
  @Prop article: ShopClass;
  // ...
}

六、交互优化设计

1. 悬停效果

.hoverEffect(HoverEffect.Scale)
.transition({ type: TransitionType.All, scale: { x: 0.95, y: 0.95 } })

2. 按钮动效

Button('加入购物车')
  .shadow({ color: '#ff6666', radius: 10 })
  .hoverEffect(HoverEffect.Scale)

七、完整代码结构

点击查看完整实现
class BannerClass {
  id: string;
  imagePath: string;
  title: string;

  constructor(id: string, imagePath: string, title: string) {
    this.id = id;
    this.imagePath = imagePath;
    this.title = title;
  }
}

class ShopClass {
  id: string;
  imagePath: string;
  title: string;
  price: string;

  constructor(id: string, imagePath: string, title: string, price: string) {
    this.id = id;
    this.imagePath = imagePath;
    this.title = title;
    this.price = price;
  }
}

@Entry
@Component
struct Index {

  private SliderImage: Array<BannerClass> = [
    new BannerClass('1', 'app.media.shop_swiper1', ''),
    new BannerClass('2', 'app.media.shop_swiper1', ''),
    new BannerClass('3', 'app.media.shop_swiper1', ''),
    new BannerClass('4', 'app.media.shop_swiper1', ''),
  ];

  private TutorialArray: Array<ShopClass> = [
    new ShopClass('1', 'app.media.shop_01', '商品1', '¥10'),
    new ShopClass('2', 'app.media.shop_02', '商品2', '¥10'),
    new ShopClass('3', 'app.media.shop_03', '商品3', '¥10'),
    new ShopClass('4', 'app.media.shop_04', '商品4', '¥10'),
    new ShopClass('5', 'app.media.shop_05', '商品5', '¥10'),
    new ShopClass('6', 'app.media.shop_06', '商品6', '¥10'),
    new ShopClass('7', 'app.media.shop_07', '商品7', '¥10'),
    new ShopClass('8', 'app.media.shop_08', '商品8', '¥10'),
    new ShopClass('9', 'app.media.shop_09', '商品9', '¥10'),
    new ShopClass('10', 'app.media.shop_10', '商品10', '¥10'),
    new ShopClass('11', 'app.media.shop_11', '商品11', '¥10'),
    new ShopClass('12', 'app.media.shop_12', '商品12', '¥10'),
  ];

  @Provide('mainStarIndex') mainStarIndex: NavPathStack = new NavPathStack();

  @Builder
  shopPage(name: string, params: ShopClass | string) {
    if (name === 'shopCartView') {
      ShopsView({
        article: params as ShopClass
      });
    }
  }

  build() {
    Navigation(this.mainStarIndex) {
      Column({ space: 15 }) {
        // 轮播图组件 - 添加自动播放和指示器
        Swiper() {
          ForEach(this.SliderImage, (item: BannerClass) => {
            Image($r(item.imagePath))
              .width('100%')
              .height(200)
              .objectFit(ImageFit.Cover)
              .borderRadius(20)
              .margin({ bottom: 10 })
          });
        }
        .autoPlay(true)
        .interval(3000)
        .indicatorStyle({ color: '#ffffff' })

        // 瀑布流布局 - 优化样式和间距
        WaterFlow() {
          ForEach(this.TutorialArray, (item: ShopClass) => {
            FlowItem() {
              this.badList(item)
            }
            .onClick(() => {
              this.mainStarIndex.pushPathByName('shopCartView', item);
            })
          });
        }
        .columnsTemplate('1fr 1fr')
        .columnsGap(15)
        .rowsGap(15)
        .padding({ left: 12, right: 12, top: 5, bottom: 10 })
        .backgroundColor('#f5f5f5')
      }
      .width('100%')
    }
    .hideTitleBar(true)
    .mode(NavigationMode.Stack)
    .navDestination(this.shopPage)
  }

  @Builder
  badList(item: ShopClass) {
    Column({ space: 10 }) {
      // 商品图片 - 添加悬停效果
      Image($r(item.imagePath))
        .width('100%')
        .height(150)
        .objectFit(ImageFit.Cover)
        .borderRadius(12)
        .transition({ type: TransitionType.All, scale: { x: 0.95, y: 0.95 } })

      // 商品标题
      Text(item.title)
        .width('100%')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .textAlign(TextAlign.Start)
        .fontFamily('HarmonyOS Sans')

      // 评分和价格
      Row() {
        // 评分部分
        Row({ space: 5 }) {
          Image($r('app.media.star'))
            .width(18)
            // .tintColor('#FFD700')
          Text('4.5')
            .fontSize(15)
            .fontColor('#666666')
        }

        // 价格
        Text(`¥${item.price}`)
          .fontSize(18)
          .fontColor('#e6393f')
          .fontWeight(FontWeight.Bold)
          .layoutWeight(1)
          .textAlign(TextAlign.End)
      }
      .width('100%')
      .alignItems(VerticalAlign.Center)
    }
    .width('100%')
    .padding({ bottom: 15 })
    .backgroundColor('#FFFFFF')
    .borderRadius(15)
    .shadow({ color: '#dcdcdc', radius: 6, offsetX: 0, offsetY: 2 })
    .margin({ bottom: 10 })
    .hoverEffect(HoverEffect.Scale) // 添加悬停缩放效果
  }
}

// 商品详细页面
@Component
export struct ShopsView {
  @Consume('mainStarIndex') mainStarIndex: NavPathStack;
  @Prop article: ShopClass;

  private SliderArray: Array<BannerClass> = [
    new BannerClass('', `${this.article.imagePath}`, ''),
    new BannerClass('', `${this.article.imagePath}`, ''),
    new BannerClass('', `${this.article.imagePath}`, ''),
    new BannerClass('', `${this.article.imagePath}`, ''),
    new BannerClass('', `${this.article.imagePath}`, ''),
  ];

  build() {
    NavDestination() {
      Stack() {
        // 轮播图 - 添加指示器和过渡效果
        Swiper() {
          ForEach(this.SliderArray, (item: BannerClass) => {
            Image($r(item.imagePath))
              .width('100%')
              .height(300)
              .objectFit(ImageFit.Cover)
              .transition({ type: TransitionType.All, opacity: 0.8, scale: { x: 0.95, y: 0.95 } })
          });
        }
        .autoPlay(true)
        .interval(3000)
        .borderRadius(20)
        .margin({ bottom: 15 })
        // 返回按钮和标题栏
        Row() {
          Image($r('app.media.black'))
            .width(30)
            .height(30)
            .onClick(() => {
              this.mainStarIndex.pop();
            })
            .margin({ right: 10 })

          Text('商品详情')
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
            .fontFamily('HarmonyOS Sans')
            .layoutWeight(1)
            .textAlign(TextAlign.Center)
            .fontColor(Color.Red)
        }
        .width('100%')
        .height(60)
        .alignItems(VerticalAlign.Bottom)
        .justifyContent(FlexAlign.Start)
        .padding({  top: 0,left: 15, right: 15})
        .position({  top: 0})
      }
      .width('100%')

        // 商品信息展示区
        Column({ space: 25 }) {
          // 商品名称
          Text(this.article.title)
            .fontSize(26)
            .fontWeight(FontWeight.Bold)
            .fontColor('#333333')
            .textAlign(TextAlign.Center)
            .width('100%')
            .margin({ bottom: 10 })

          // 价格标签
          Row() {
            Text(`¥${this.article.price.split('¥')[1]}`)
              .fontSize(24)
              .fontColor('#e6393f')
              .fontWeight(FontWeight.Bold)

            Text('已售 1000+')
              .fontSize(14)
              .fontColor('#999999')
              .margin({left: 10})
          }
          .width('100%')
          .padding({ left: 20, right: 20 })

          // 商品描述
          Text('这里是商品的详细描述,可以包含材质、尺寸、产地等重要信息。您可以通过滚动查看完整的商品介绍。')
            .fontSize(16)
            .fontColor('#555555')
            .lineHeight(26)
            .textAlign(TextAlign.Start)
            .width('100%')
            .padding({ left: 20, right: 20 })

          // 分割线
          Divider()
            .strokeWidth(1)
            .color('#eeeeee')
            .margin({ top: 15, bottom: 15 })

          // 商品特色图标
          Row({ space: 30 }) {
            Column() {
              Image($r('app.media.background'))
                .width(25)
                .height(25)
              Text('快递包邮')
                .fontSize(14)
                .fontColor('#666666')
            }

            Column() {
              Image($r('app.media.background'))
                .width(25)
                .height(25)
              Text('7天退换')
                .fontSize(14)
                .fontColor('#666666')
            }

            Column() {
              Image($r('app.media.background'))
                .width(25)
                .height(25)
              Text('正品保障')
                .fontSize(14)
                .fontColor('#666666')
            }
          }
          .width('100%')
          .justifyContent(FlexAlign.SpaceEvenly)
          .padding({ left: 20, right: 20 })

          // 加入购物车按钮
          Button('加入购物车')
              .width(20)
              .height(20)
              .margin({ right: 10 })
          .onClick(() => {
            // 这里可以添加购物车逻辑
          })
          .width(240)
          .height(50)
          .fontSize(18)
          .backgroundColor('#ff4444')
          .borderRadius(30)
          .margin({ top: 25 })
          .shadow({ color: '#ff6666', radius: 10, offsetX: 0, offsetY: 4 })
          .hoverEffect(HoverEffect.Scale)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Center)
        // .padding({ top:10, bottom: 30 })
        .backgroundColor('#f9f9f9')
    }
    .hideTitleBar(true)
    .onBackPressed(() => {
      // 自定义返回逻辑
      this.mainStarIndex.pop();
      return true;
    });
  }
}

八、设计要点总结

  1. 分层架构:清晰的数据层、UI层、业务逻辑层分离
  2. 组件化:通过@Builder构建可复用UI组件
  3. 状态管理:@Provide/@Consume实现跨组件数据共享
  4. 交互优化:悬停效果、过渡动画增强用户体验
  5. 导航系统:NavPathStack实现页面堆栈管理
收藏00

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