
网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
📣 公众号"Swift社区",每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友"fzhanfei",与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
引言
很多开发者刚开始接触 ArkUI(ArkTS) 的时候,都会觉得状态管理非常简单。因为官方示例看起来通常是这样的:
ts
@State count: number = 0
然后在按钮里修改:
ts
this.count++
页面就会自动刷新,于是很多人得出一个结论:
ArkUI 的状态管理很简单。
但当项目开始变大之后,问题就慢慢出现了:
页面状态越来越多
组件之间数据传递混乱
刷新逻辑变得难以理解
甚至很多项目会出现一种情况:
改一个状态,整个页面都在刷新。
这其实并不是 ArkUI 的问题,而是很多开发者 一开始就把状态用错了。
ArkUI 的状态设计,其实有明确分层
如果仔细看 ArkUI 的状态设计,你会发现它并不是只有 @State。ArkUI 实际提供了一整套状态工具:
@State
@Prop
@Link
@Provide
@Consume
@Observed
@ObjectLink
这些装饰器的存在,其实说明了一件事:
ArkUI 的状态是有层级设计的。
大致可以分为三类:
1、页面本地状态
例如:
ts
@State
这种状态通常只属于当前组件,典型场景:
按钮点击
输入框内容
UI 展开收起
也就是说:
只影响当前组件 UI 的状态。
2、父子组件状态
例如:
@Prop
@Link
它们主要用于 组件通信,简单理解:
父组件
↓
子组件
例如:
ts
@Component
struct Parent {
@State count: number = 0
build() {
Child({ count: this.count })
}
}
子组件:
ts
@Component
struct Child {
@Prop count: number
}
如果需要双向绑定,就可以使用:
@Link
这种设计和很多现代 UI 框架其实很像。
3、全局共享状态
例如:
@Provide
@Consume
用于跨组件共享数据,例如:
ts
@Provide userInfo: User
子组件中:
ts
@Consume userInfo: User
这种方式适合:
用户信息
主题
全局配置
也就是说:
ArkUI 其实已经提供了完整的状态分层方案。
但问题是------很多项目 根本没有按这个方式使用。
常见错误 1:所有状态都用 @State
这是最常见的问题,很多项目会出现这样的代码:
ts
@State userName: string = ""
@State userAvatar: string = ""
@State userAge: number = 0
@State userAddress: string = ""
看起来没有问题,但如果这些数据其实是:
全局用户信息
那问题就来了,因为:
多个页面都会有这些状态
于是项目里就会出现:
重复状态
数据不同步
状态混乱
正确做法其实应该是:
全局状态
例如:
ts
@Provide userStore: UserStore
然后组件通过:
@Consume
获取数据。
常见错误 2:组件层级传递太深
很多 ArkUI 项目会出现一种情况:
页面
↓
组件A
↓
组件B
↓
组件C
然后数据从最上层一直传:
ts
ChildA({ user: this.user })
ChildB({ user: this.user })
ChildC({ user: this.user })
这在小项目里没问题,但在复杂页面里,代码会变成:
一条很长的数据传递链。
这就是经典的:
prop drilling
解决方案其实就是:
@Provide
@Consume
让中间组件 不需要知道数据存在。
常见错误 3:对象状态不会刷新
很多人第一次写 ArkUI 时都会遇到一个问题:
ts
@State user: User = new User()
然后更新属性:
ts
this.user.name = "Tom"
UI 却 没有刷新,这是因为 ArkUI 的状态更新机制是:
引用变化触发刷新。
而不是对象内部变化,所以正确做法通常是:
ts
this.user = { ...this.user, name: "Tom" }
或者使用:
@Observed
来观察对象变化。
常见错误 4:状态和业务逻辑混在一起
很多项目还会出现一个问题,页面代码变成这样:
ts
@State cartItems: Item[] = []
@State totalPrice: number = 0
@State discount: number = 0
然后在 UI 代码里写业务逻辑:
ts
this.totalPrice = this.cartItems.reduce(...)
结果页面代码变得非常混乱,更合理的方式其实是:
状态管理
业务计算
UI 渲染
分开,例如:
CartStore
负责:
商品列表
价格计算
优惠逻辑
而页面只负责:
展示
一个更合理的 ArkUI 状态结构
在中大型项目里,比较常见的结构是:
UI State
↓
ViewModel / Store
↓
Service
例如:
Page
↓
UserStore
↓
UserService
职责分别是:
Page → UI
Store → 状态管理
Service → 数据获取
这样做有几个好处:
状态统一
逻辑清晰
代码可维护
为什么很多 ArkUI 项目容易写乱
原因其实很简单,ArkUI 的示例代码通常都非常简单:
ts
@State
这让很多开发者产生一种错觉:
状态随便放在哪里都行。
但在真实项目里:
状态设计 = 架构设计
一旦项目规模变大,如果没有明确的状态边界,代码很快就会变得难以维护。
总结
很多开发者觉得 ArkUI 状态管理很简单,其实只是因为:
项目还不够大。
当应用规模扩大之后,状态问题很容易暴露:
状态重复
组件耦合
刷新异常
逻辑混乱
而 ArkUI 其实已经提供了一整套完整的状态管理工具:
@State
@Prop
@Link
@Provide
@Consume
@Observed
关键不在于 有没有工具,而在于:
有没有正确理解状态的边界。
如果状态设计合理,ArkUI 的项目其实可以非常清晰。但如果一开始就随意使用状态装饰器,那么项目很容易走向一个结局:
页面能跑,但没人敢改。