1. 页面结构与多组件写法

  • 一个 .ets 文件里可以写 多个组件:一个 @Entry 页面组件 + 若干普通子组件。
  • @Entry 有且只能有一个,表示页面入口。
  • 子组件只加 @Component,不加 @Entry

2. 响应式状态:@State

  • 作用:数据改变 → 页面自动刷新(对应 Vue 的 ref)。

  • 用法:

    @State cartCount: number = 0

  • 修改变量必须用 this.xxx,否则报错。

3. 父子组件传值(今天最重点)

① 传基础类型(string /number/boolean)

  • @Prop
  • 最简单、最安全,不会报错

② 传对象 / 复杂数据

  • 必须用:@Observed 类 + @ObjectLink

    1. 先定义被观察类:

      @Observed class ProductItem { 
          name: string;
          price: number;
          image: string 
              constructor(name: string, price: number, image: string) { 
                  this.name = name; 
                  this.price = price; 
                  this.image = image 
              } 
      }

    2. 父组件用 new ProductItem() 创建实例

    3. 子组件用 @ObjectLink product: ProductItem 接收

③ 传函数 / 回调事件

  • 直接写函数名,不需要任何装饰器

    onAddToCart: () => void

4. 点击事件

  • 语法:.onClick(() => { })
  • 对应 Vue 的 @click,逻辑完全一样。

5. 布局与样式回顾

  • Column():垂直布局(默认从上到下)
  • Row():水平布局(默认从左到右)
  • Blank():自动撑开空白(实现左右对齐)
  • 阴影:.shadow({ radius, color, offsetX, offsetY })

6. 鸿蒙 ↔ Vue 关键区别(必记)

  1. Vue 可以直接 props 传对象,鸿蒙不行
  2. Vue 不用写 this.,鸿蒙必须写
  3. Vue 构造函数可写键值对,TS / 鸿蒙只能按顺序传参
  4. 鸿蒙对象传参强制要求 @Observed + @ObjectLink

7. 今天遇到的经典报错避坑

  1. @Prop 不支持对象 → 对象改用 @ObjectLink
  2. @ObjectLink 必须搭配 @Observed 类 → 把对象包成 class
  3. Cannot find name 'name' → 少写了 this.
  4. new 构造函数不能写 key:value → 直接按顺序传参

示例代码

@Observed
class ProductItem {
  name: string;
  price: number;
  image: string

  constructor(name: string, price: number, image: string) {
    this.name = name;
    this.price = price;
    this.image = image
  }
}

@Component
struct ProductCard {
  @ObjectLink product: ProductItem
  onAddToCart: () => void

  build() {
    Column() {
      Image(this.product.image)
        .width(200)
        .height(200)
        .objectFit(ImageFit.Contain)
        .margin({ bottom: 15 })
      Text(this.product.name)
        .fontSize(20)
        .fontWeight(FontWeight.Medium)
        .margin({ bottom: 10 })
      Text(`¥${this.product.price}`)
        .fontSize(24)
        .fontColor('#ff6600')
        .fontWeight(FontWeight.Bold)
      Button('加入购物车')
        .width('100%')
        .height(45)
        .onClick(() => {
          this.onAddToCart()
        })

    }
    .width('90%')
    .padding(20)
    .backgroundColor('#fff')
    .borderRadius(16)
    .shadow({
      color: '#ddd',
      radius: 8,
      offsetX: 2,
      offsetY: 2
    })
  }
}

@Entry
@Component
struct IndexDemo {
  @State cartCount: number = 0
  @State product: ProductItem = new ProductItem(
    "鸿蒙开发学习",
    100,
    "https://res2.vmallres.com/pimages/uomcdn/CN/pms/202403/gbom/6942103109560/428_428_9D3B788CDF5A83F6820BCA9411A6899Dmp.png"
  )

  build() {
    Column() {
      Row() {
        Text("极简购物商城")
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
        Blank()
        Text(`购物车:${this.cartCount}`)
          .fontSize(18)
          .fontColor('#ff6600')
      }
      .width('100%')
      .padding({ left: 20, right: 20, top: 20, bottom: 20 })

      ProductCard({
        product: this.product,
        onAddToCart: () => {
          this.cartCount++
        }
      })
        .margin({ top: 20 })

    }
    .width("100%")
    .height("100%")
    .backgroundColor("#f2f3f5")

  }
}

export default IndexDemo

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐