HarmonyOS 「星办OA」App应用实战28 : @Local装饰器与组件局部状态
# @Local装饰器与组件局部状态
一、引言
在HarmonyOS NEXT的ArkUI框架中,@Local装饰器是@ComponentV2体系下管理组件局部状态的核心工具。它替代了传统@Component中的@State装饰器,提供了更清晰的状态声明、更明确的更新触发机制,以及与@Param/@Event装饰器的协同能力。
在"星办OA"企业办公审批项目中,@Local被广泛应用于所有页面的状态管理中——从审批中心的视图切换、筛选条件,到详情页的审批数据加载,再到个人中心的开关状态。本文将深入分析@Local装饰器的使用方式、生命周期和行为特性,并结合项目中的实际代码,探讨组件局部状态管理的最佳实践。

二、@Local装饰器基础
2.1 基本声明
在@ComponentV2中,@Local用于声明组件的局部状态:
@ComponentV2
export struct OfficePage {
@Local selectedView: string = ApprovalView.PENDING // 当前选中的视图
@Local selectedType: string = '全部' // 当前选中的审批类型
@Local keyword: string = '' // 搜索关键词
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(ApprovalStore, () => new ApprovalStore())!
}
@Local修饰的变量具有以下特性:
- 局部作用域:状态属于当前组件实例,其他组件不可直接访问
- 响应式更新:当值变化时,组件自动重新渲染
- 初始化时机:在组件创建时初始化
2.2 与@State的对比
在@ComponentV2出现之前,@State是管理局部状态的主要方式。@Local与@State的核心区别:
| 特性 | @State | @Local |
| 所属框架 | @Component | @ComponentV2 |
| 声明方式 | 装饰器 | 装饰器 |
| 更新机制 | 自动检测 | 自动检测 |
| 与@Param协同 | 不支持 | 支持 |
| 与@Event协同 | 不支持 | 支持 |
三、@Local在项目中的典型应用
3.1 视图切换状态
在审批中心(OfficePage.ets)中,@Local用于管理视图切换和筛选状态:
@ComponentV2
export struct OfficePage {
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(ApprovalStore, () => new ApprovalStore())!
@Local selectedView: string = ApprovalView.PENDING // 当前视图:待我审批
@Local selectedType: string = '全部' // 当前筛选类型
@Local keyword: string = '' // 搜索关键词
}
这三个@Local变量共同决定了审批列表的显示内容:
private getVisibleApprovals(): ApprovalRequest[] {
return this.store.getFilteredApprovals(this.selectedView, this.selectedType, this.keyword)
}
当用户切换视图、选择类型或输入搜索关键词时,对应的@Local变量发生变化,组件重新渲染,审批列表随之更新。
视图切换逻辑:
@Builder
private buildViewTabs() {
Row() {
ForEach(this.views, (view: string) => {
Column({ space: 7 }) {
Text(view)
.fontColor(this.selectedView === view ? '#2459E0' : '#667085')
Divider()
.color(this.selectedView === view ? '#3B6FF5' : Color.Transparent)
}
.onClick(() => {
this.selectedView = view // 更新@Local变量
this.selectedType = '全部'
this.keyword = ''
})
})
}
}
3.2 搜索状态管理
在审批中心的搜索栏中,@Local keyword管理搜索关键词:
@Builder
private buildSearchBar() {
Row({ space: 8 }) {
Text('⌕')
TextInput({ text: this.keyword, placeholder: '搜索标题、申请人或审批单号' })
.onChange((value: string) => this.keyword = value)
if (this.keyword.length > 0) {
Text('清除')
.onClick(() => this.keyword = '')
}
}
}
搜索关键词的变化通过@Local的响应式机制,自动触发列表过滤和重新渲染。清除按钮通过将keyword设置为空字符串,恢复完整列表。
3.3 审批详情页状态
在审批详情页(ApprovalDetailPage.ets)中,@Local管理多个状态变量:
@ComponentV2
export struct ApprovalDetailPage {
@Param approvalId: string = ''
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(ApprovalStore, () => new ApprovalStore())!
@Local approval: ApprovalRequest = new ApprovalRequest() // 当前审批数据
@Local found: boolean = false // 是否找到审批
@Local comment: string = '' // 审批意见
}
数据加载状态管理:
aboutToAppear(): void {
this.reloadApproval()
}
private reloadApproval(): void {
let item: ApprovalRequest | undefined = this.store.getApproval(this.approvalId)
if (item === undefined) {
this.found = false // 更新@Local变量,渲染"未找到"页面
return
}
this.approval = item // 更新@Local变量,触发重新渲染
this.found = true
}
条件渲染控制:
build() {
NavDestination() {
if (!this.found) {
// 未找到审批的提示页面
Column({ space: 12 }) {
Text('!')
Text('未找到这条审批')
Button('返回').onClick(() => this.pageInfos.pop())
}
} else {
// 审批详情内容
Column() {
Scroll() {
Column({ space: 14 }) {
this.buildStatusCard()
this.buildBaseInformation()
// ...
}
}
this.buildActionBar()
}
}
}
}
found和approval两个@Local变量协同工作,控制页面的状态切换。当found为false时渲染"未找到"页面,为true时渲染审批详情。
3.4 审批表单状态
在审批创建页(ApprovalCreatePage.ets)中,@Local管理表单输入状态:
@ComponentV2
export struct ApprovalCreatePage {
@Param approvalType: string = '请假'
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(ApprovalStore, () => new ApprovalStore())!
@Local selectedType: string = '请假' // 选中的审批类型
@Local title: string = '' // 申请标题
@Local summary: string = '' // 业务明细
@Local reason: string = '' // 申请事由
}
表单验证逻辑依赖于这些@Local变量:
private confirmSubmit(): void {
if (this.title.trim().length === 0 || this.summary.trim().length === 0 || this.reason.trim().length === 0) {
promptAction.showToast({ message: '请填写申请标题、业务明细和申请事由' })
return
}
// 提交逻辑
}
3.5 个人中心开关状态
在个人中心(MinePage.ets)中,@Local管理开关状态:
@ComponentV2
export struct MinePage {
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(ApprovalStore, () => new ApprovalStore())!
@Local approvalNotificationEnabled: boolean = true // 待办审批提醒开关
@Local resultNotificationEnabled: boolean = true // 审批结果提醒开关
}
开关状态通过Toggle组件控制:
@Builder
private buildToggleSetting(kind: string) {
Row({ space: 12 }) {
// 图标和文字
Toggle({ type: ToggleType.Switch, isOn: this.isToggleEnabled(kind) })
.onChange((enabled: boolean) => this.setToggleEnabled(kind, enabled))
}
}
private isToggleEnabled(kind: string): boolean {
return kind === '待办' ? this.approvalNotificationEnabled : this.resultNotificationEnabled
}
private setToggleEnabled(kind: string, enabled: boolean): void {
if (kind === '待办') {
this.approvalNotificationEnabled = enabled
} else {
this.resultNotificationEnabled = enabled
}
}
四、@Local与@Param/@Event的协同
4.1 三者的分工
在@ComponentV2中,@Local、@Param和@Event三者各有分工:
- @Param:接收父组件传入的参数,只读
- @Local:管理组件自身的局部状态,可读写
- @Event:向父组件传递事件,用于反向通信
4.2 协同示例
在审批详情页中,三者协同工作:
@ComponentV2
export struct ApprovalDetailPage {
@Param approvalId: string = '' // 父组件传入的审批ID(只读)
@Local store: ApprovalStore = ... // 局部状态(可读写)
@Local approval: ApprovalRequest = ... // 局部状态(可读写)
@Local found: boolean = false // 局部状态(可读写)
@Local comment: string = '' // 局部状态(可读写)
@Consumer('pageInfos') pageInfos: NavPathStack = new NavPathStack()
}
approvalId由@Param从父组件接收,用于加载审批数据approval、found、comment由@Local管理,用于维护页面状态pageInfos通过@Consumer从祖先组件获取,用于导航操作
五、@Local的生命周期
5.1 初始化
@Local变量在组件创建时初始化,初始值在声明时指定:
@Local selectedView: string = ApprovalView.PENDING // 初始值为"待我审批"
@Local keyword: string = '' // 初始值为空字符串
@Local found: boolean = false // 初始值为false
5.2 更新触发
@Local变量的更新触发组件重新渲染:
// 用户点击视图标签 -> 更新selectedView -> 组件重新渲染
.onClick(() => {
this.selectedView = view
this.selectedType = '全部'
this.keyword = ''
})
5.3 销毁
当组件被销毁时,@Local变量的值也随之释放。这意味着@Local状态是组件实例级别的,不会跨实例共享,也不会持久化。
六、最佳实践
6.1 状态粒度控制
@Local变量的粒度应该适中:
- 太粗:一个对象包含所有状态,局部变化可能触发不必要的渲染
- 太细:每个变量管理一个独立状态,可能导致大量@Local声明
6.2 与AppStorageV2的配合
对于需要跨页面共享的状态,使用AppStorageV2连接全局仓库;对于页面内的临时状态,使用@Local管理:
@Local store: ApprovalStore = AppStorageV2.connect<ApprovalStore>(...) // 全局共享
@Local keyword: string = '' // 页面局部
6.3 条件渲染
使用@Local变量控制条件渲染,可以实现页面状态的切换:
if (!this.found) {
// 加载失败状态
} else {
// 正常显示状态
}
七、总结
@Local装饰器是@ComponentV2体系中管理组件局部状态的核心工具。它提供了响应式的状态管理能力,当变量值变化时自动触发组件重新渲染。
在"星办OA"项目中,@Local被广泛应用于所有页面:审批中心的视图切换(selectedView)、筛选类型(selectedType)和搜索关键词(keyword),审批详情页的数据加载状态(found)和审批意见(comment),审批创建页的表单输入(title、summary、reason),个人中心的开关状态(approvalNotificationEnabled、resultNotificationEnabled)等。
@Local与@Param/@Event的协同分工,使得组件状态管理既清晰又灵活——@Param接收外部输入,@Local管理内部状态,@Event向外部输出。这种设计模式,是构建可维护、可测试的企业级应用的基础。
更多推荐


所有评论(0)