在ArkUI框架中,状态管理是构建动态应用的核心。以下是
组件级别
和应用级别
状态管理装饰器的分类、用途及区别的总结,结合了思考过程中的关键点:
一、组件级别状态管理
1. @State
- 用途:组件内部私有状态,变化触发UI更新。
- 示例:按钮的点击状态、计数器数值。
- 特点:只能初始化一次,单向数据流(组件内修改)。
代码示例:
javascript
@Component
struct CounterButton {
@State count: number = 0; // 组件内部状态
build() {
Button(`点击次数:${this.count}`)
.onClick(() => {
this.count++; // 修改@State变量自动更新UI
})
}
}
2. @Prop
- 用途:父组件向子组件传递数据(单向)。
- 特点:需通过父组件回调更新数据。
- 示例:显示父组件传递的文本,子组件不可直接修改。
代码示例:
javascript
// 父组件
@Component
struct ParentComponent {
@State parentCount: number = 0;
build() {
Column() {
ChildComponent({ countProp: this.parentCount }) // 传递数据
Button("父组件增加").onClick(() => this.parentCount++)
}
}
}
// 子组件
@Component
struct ChildComponent {
@Prop countProp: number; // 单向接收父组件数据
build() {
Text(`来自父组件的值:${this.countProp}`)
}
}
3. @Link
- 用途:父子组件双向数据绑定。
- 特点 :双向同步,类似Vue的
v-model
。 - 示例:共享开关状态,子组件直接修改影响父组件。
代码示例:
javascript
// 父组件
@Component
struct ParentComponent {
@State sharedCount: number = 0;
build() {
Column() {
ChildComponent({ countLink: $sharedCount }) // 双向绑定
Text(`父组件值:${this.sharedCount}`)
}
}
}
// 子组件
@Component
struct ChildComponent {
@Link countLink: number; // 双向绑定变量
build() {
Button("子组件修改").onClick(() => {
this.countLink++; // 修改会同步到父组件
})
}
}
4. @Provide / @Consume
- 用途:跨层级组件数据共享(祖先→后代)。
- 示例:主题颜色全局设置。
- 特点:避免逐层传递,类似React Context。
代码示例:
javascript
// 祖先组件
@Component
struct AncestorComponent {
@Provide themeColor: string = 'blue'; // 提供数据
build() {
Column() {
ChildComponent()
}
}
}
// 后代组件
@Component
struct ChildComponent {
@Consume themeColor: string; // 消费数据
build() {
Text(`当前主题色:${this.themeColor}`)
.fontColor(this.themeColor)
}
}
5. @Observed / @ObjectLink
- 用途:观察嵌套对象属性变化。
- 特点 :
@Observed
装饰类,@ObjectLink
引用实例。 - 示例 :用户对象(
{name: string}
)属性更新。
代码示例:
javascript
@Observed // 装饰类
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@Component
struct UserProfile {
@ObjectLink user: User; // 引用被观察对象
build() {
Column() {
Text(`姓名:${this.user.name}`)
Button("修改年龄").onClick(() => {
this.user.age++; // 修改会触发UI更新
})
}
}
}
6. @Style
- 用途:定义可复用的组件样式。
- 示例:统一按钮样式(颜色、边距)。
代码示例:
javascript
@Styles function customButtonStyle() {
.width(120)
.height(40)
.backgroundColor(Color.Blue)
.fontColor(Color.White)
}
@Component
struct StyledButton {
build() {
Button("样式按钮")
.useStyle(customButtonStyle) // 应用样式
}
}
7. @Builder / @BuilderParam
- 用途:构建可复用的UI片段或动态插入布局。
- 示例:自定义卡片布局,父组件传递头部Builder。
- 区别 :
@Builder
定义结构,@BuilderParam
接收结构作为参数。
代码示例:
javascript
@Component
struct CustomCard {
@BuilderParam header: () => void; // 接收Builder参数
build() {
Column() {
this.header() // 插入自定义头部
Text("卡片内容...")
}
}
}
// 使用组件时传递Builder
CustomCard({
header: () => {
Text("自定义标题")
.fontSize(20)
.fontColor(Color.Red)
}
})
8. @Extend
- 用途:扩展组件样式(如全局字体)。
- 示例:统一所有文本的字体大小和颜色。
代码示例:
javascript
@Extend(Text) function boldText() {
.fontWeight(FontWeight.Bold)
.fontColor('#333')
}
@Component
struct ExtendedText {
build() {
Column() {
Text("普通文本")
Text("加粗文本").useStyle(boldText) // 应用扩展样式
}
}
}
二、应用级别状态管理
1. @LocalStorage
- 用途:页面级临时存储(页面关闭后可能保留)。
- 示例:表单草稿保存。
补充知识点: @LocalStorageProp / @LocalStorageLink
区别:前者单向同步,后者双向绑定页面存储数据。
代码示例:
javascript
// 页面A
@Entry
@Component
struct PageA {
@LocalStorage('formData') formData: string = '';
build() {
TextInput(this.formData)
.onChange((value) => {
this.formData = value; // 数据保存到LocalStorage
})
}
}
// 页面B可读取同一LocalStorage
@Component
struct PageB {
@LocalStorage('formData') formData: string;
build() {
Text(`保存的数据:${this.formData}`)
}
}
2. @AppStorage
- 用途:全局状态存储(应用生命周期内有效)。
- 示例:用户登录Token。
补充知识点: @StorageProp / @StorageLink
用途 :绑定到
AppStorage
中的具体键。区别 :
@StorageProp
单向,@StorageLink
双向。
代码示例:
javascript
// 全局存储用户Token
@AppStorage.setOrCreate('userToken', '') // 初始化
@Component
struct LoginComponent {
@StorageLink('userToken') token: string; // 双向绑定
build() {
Button("登录").onClick(() => {
this.token = 'abc123'; // 修改全局状态
})
}
}
// 其他页面读取
@Component
struct ProfilePage {
@StorageProp('userToken') token: string; // 单向读取
build() {
Text(`Token: ${this.token}`)
}
}
3. @PersistentStorage
- 用途:持久化存储(应用重启保留)。
- 示例:用户偏好设置(语言、主题)。
代码示例:
javascript
@PersistentStorage.setOrCreate('settings', { theme: 'light', fontSize: 16 })
@Component
struct SettingsPage {
@StorageLink('theme') theme: string;
@StorageLink('fontSize') fontSize: number;
build() {
Column() {
Button("切换主题").onClick(() => {
this.theme = this.theme === 'light' ? 'dark' : 'light';
})
Slider({ min: 12, max: 24 })
.value(this.fontSize)
.onChange((value) => {
this.fontSize = value;
})
}
}
}
4. @Environment
- 用途:访问环境变量(如主题、语言)。
- 示例:根据系统主题切换应用外观。
代码示例:
javascript
@Component
struct ThemeAwareComponent {
@Environment('currentTheme') theme: string;
build() {
Text("主题敏感文本")
.fontColor(this.theme === 'dark' ? Color.White : Color.Black)
.backgroundColor(this.theme === 'dark' ? Color.Black : Color.White)
}
}
三、关键区别与选择
-
作用域:
- 组件级:
@State
、@Prop
等用于组件或父子通信。 - 应用级:
@AppStorage
、@PersistentStorage
等跨页面共享。
- 组件级:
-
数据流:
- 单向:
@Prop
、@LocalStorageProp
(父→子/存储→组件)。 - 双向:
@Link
、@LocalStorageLink
(父子/组件与存储同步)。
- 单向:
-
持久性:
- 临时:
@State
、@LocalStorage
(页面级)。 - 持久:
@PersistentStorage
(设备存储)。
- 临时:
-
使用场景:
- 简单组件状态 →
@State
。 - 跨组件共享 →
@Provide
/@Consume
。 - 全局配置 →
@AppStorage
+@StorageLink
。 - 复杂对象监听 →
@Observed
+@ObjectLink
。
- 简单组件状态 →
四、最佳实践总结
- 简单交互优先使用
@State
:适合按钮状态、临时计数等 - 父子通信选择
@Prop
/@Link
:单向传递用@Prop
,双向同步用@Link
- 跨层级共享数据用
@Provide
/@Consume
:避免多级传递的麻烦 - 全局状态使用
@AppStorage
:如用户登录状态、主题配置 - 复杂对象监听用
@Observed
+@ObjectLink
:确保嵌套属性变化触发更新 - 持久化数据用
@PersistentStorage
:用户设置、历史记录等需要长期保存的数据
官方文档是更全面的参考:
HarmonyOS ArkUI 文档