🧱 写在前面
很多 React 开发者初学 ArkTS 时,看到这样的代码会一脸困惑:
ts
@Component
struct Greeting {
build() {
Text('Hello')
}
}
"为什么是
struct?不是function?这和我的function App() {}有什么关系?"
答案是:@Component + struct 就是 ArkTS 的"函数组件",只是采用了更安全、更高效的声明方式。
本期我们将用 React 的思维,彻底搞懂鸿蒙的组件定义模型,打通从 JSX 到声明式 UI 的认知桥梁。
🔧 1. 为什么不用 function?因为 struct 更适合声明式 UI
React 函数组件(你熟悉的写法)
ts
function Greeting({ name }: { name: string }) {
return <p>Hello, {name}!</p>;
}
ArkTS 组件(鸿蒙的等价写法)
ts
@Component
struct Greeting {
name: string; // ← props 声明为 struct 成员
build() {
Text(`Hello, ${this.name}!`)
}
}
✅ 为什么选择 struct 而非 function?
| 维度 | React 函数组件 | ArkTS struct 组件 |
|---|---|---|
| 执行模型 | 每次渲染调用函数 | 编译为原生结构体,无函数调用开销 |
| 类型安全 | 依赖 TypeScript 接口 | 成员变量显式声明,编译时强校验 |
| 状态访问 | 依赖闭包(可能 stale) | 直接访问 this.count,无闭包陷阱 |
| 内存效率 | JS 引擎 GC 管理 | ArkTS 运行时自动管理,更适合端侧设备 |
💡 核心思想一致 :组件是 UI 的纯函数 ------ 输入(props)→ 输出(UI)。
只是 ArkTS 选择了更适合高性能、低功耗场景的实现方式。
📦 2. Props 怎么传?成员变量就是你的 props!
在 React 中,props 是函数参数;在 ArkTS 中,props 是 struct 的成员变量。
使用示例
ts
// 定义组件
@Component
struct MyButton {
label: string; // 必填 props
onClick?: () => void; // 可选 props(注意 ?)
build() {
Button(this.label)
.onClick(() => this.onClick?.()) // 安全调用
}
}
// 使用组件
MyButton({
label: '提交',
onClick: () => console.log('clicked')
})
🔑 关键规则
- 所有 props 必须在
struct中显式声明类型 - 可选 props 用
?标记(如onClick?: () => void) - 调用时通过
{ prop: value }传递,语法与 React 几乎一致
✅ 这比 React 的
PropTypes或interface更直接------类型即文档,编译即校验。
🔄 3. 组件复用:组合优于继承(完全兼容 React 思维)
ArkTS 同样推崇"组合"而非"继承"。下面是一个用户卡片的组合示例:
ts
// 子组件:头像
@Component
struct Avatar {
src: Resource; // 鸿蒙资源类型
size: number = 40; // 默认值
build() {
Image(this.src)
.width(this.size)
.height(this.size)
.borderRadius(this.size / 2)
}
}
// 子组件:用户名
@Component
struct UserName {
name: string;
isVIP: boolean = false;
build() {
Text(this.name)
.fontSize(this.isVIP ? 18 : 16)
.fontColor(this.isVIP ? '#e91e63' : '#333')
.fontWeight(FontWeight.Bold)
}
}
// 父组件:组合使用
@Component
struct UserCard {
avatarSrc: Resource;
userName: string;
isVIP: boolean = false;
build() {
Row() {
Avatar({ src: this.avatarSrc })
UserName({ name: this.userName, isVIP: this.isVIP })
}
.alignItems(VerticalAlign.Center)
.padding(10)
}
}
💡 你会发现:
- 每个组件职责单一
- 通过
Child({ ... })组合使用- 完全符合 React 的"组合哲学"
⚠️ 4. 新手常见错误(避坑指南)
❌ 错误 1:未提供默认值,导致 props 必传
ts
@Component
struct Title {
text: string; // ← 无默认值,使用时必须传
size: number; // ← 同样必须传,否则编译失败
}
✅ 正确做法:提供默认值,让 props 可选
ts
size: number = 16; // ← 有默认值,可不传
❌ 错误 2:在 build() 外访问 this
ts
@Component
struct Counter {
@State count: number = 0;
console.log(this.count); // ❌ 编译错误!不能在 build 外用 this
build() {
Button(`Count: ${this.count}`) // ✅ 正确
}
}
✅ 正确:所有 UI 相关逻辑必须放在 build() 方法或事件回调中。
✅ 小结
- ✅
@Component struct X≈function X(props) - ✅ 成员变量 = props(显式声明,类型安全)
- ✅
build()=return (JSX)(UI 构建入口) - ✅ 组件组合方式完全一致:
Child({ prop: value }) - ✅ 无生命周期方法,无 class,无 this 绑定问题
你不是在学习面向对象,而是在用更安全、更高效的方式写函数式 UI。
🔜 下期预告
《useState 换个名字叫 @State,仅此而已》
我们将深入:
- 如何声明组件状态?
- 父子组件如何通信(
@Propvs@Link)?- 为什么直接赋值就能自动刷新 UI?
关注我,持续解锁 React → 鸿蒙实战技能!
📚 参考资料
- 学习UI范式基本语法
系列名称 :《React 开发者的鸿蒙入门指南》
✅ 欢迎点赞、收藏、评论交流!你的支持是我持续输出的动力!
✅ 点击主页关注,获取更多前端 × 鸿蒙实战内容!
💬 互动提问 :你觉得
struct比function更难理解吗?你在定义组件时遇到过哪些编译错误?留言告诉我,我会在下期集中解答!