鸿蒙开发vs前端开发1-父子组件传值

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

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

2. 响应式状态:@State

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

  • 用法:

    css 复制代码
    @State cartCount: number = 0
  • 修改变量必须用 this.xxx,否则报错。

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

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

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

② 传对象 / 复杂数据

  • 必须用:@Observed 类 + @ObjectLink

    1. 先定义被观察类:

      ts

      typescript 复制代码
      @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 → 直接按顺序传参

示例代码

less 复制代码
@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
相关推荐
花开盛夏^.^4 小时前
电脑打开多个浏览器Web窗口占用较大的运行内存的原因
前端·浏览器
馒头不想说话5 小时前
实体店老板的24小时AI运营员工,写、剪、发全自动,省下一整个团队工资
前端
椒哥7 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
风骏时光牛马7 小时前
生成一个AI稳定性治理及疑难问题分析标题,只需要一个标题,不需要其他的任何文本。
前端
莫西干式秃头7 小时前
用 AI + threejs 写了个浏览器里的 3D 动作游戏《武来》:砍怪、放技能、开 SU7
前端·人工智能·three.js
kyriewen7 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
孟健7 小时前
用 WorkBuddy 做个人名片网页,挂上开源设计技能后效果完全不同了
前端·人工智能·ai编程
IT_陈寒8 小时前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端
LuHang9 小时前
从天地图切换到高德地图:一次真实的底图迁移实战
前端·vue.js·cesium
用户360055579009 小时前
Kestrel_VLLM - 27 · 寄存器常驻与融合发射:两次「少发一次」
前端