鸿蒙开发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
相关推荐
jinanwuhuaguo11 小时前
OpenClaw执行奇点——因果链折叠与责任悬置的时间哲学(第十九篇)
前端·人工智能·安全·重构·openclaw
为美好的生活献上中指11 小时前
本地虚拟机部署redis集群
前端·redis·ubuntu·bootstrap·html·redis集群
ConardLi12 小时前
开源我的 GPT-Image2 生图 Skill,附大量玩法指南
前端·人工智能·后端
我是Superman丶12 小时前
Antigravity Retry 自动重试脚本
前端·javascript·vue.js
是大强12 小时前
nvm安装node成功npm失败
前端·npm·node.js
\xin12 小时前
pikachu自编CSRF(GET),CSRF(POST),CSRF(token)
前端·csrf
是大强12 小时前
前端一个项目用node20 一个项目用node14 怎么切换
前端
不老刘12 小时前
Git Cherry-Pick:微前端架构下的“精准医疗”与最佳实践
前端·git
LIO13 小时前
ESLint 极简指南:让代码既规范又一致
前端·eslint
明月_清风13 小时前
前端工程化七连问:从紧急修复到版本控制,一文打通工程化任督二脉
前端·前端工程化