ArkTS状态管理装饰器V1版本(@State、@Prop、@Link、@ObjectLink、@Provide、@Consume、@StorageProp、@StorageLink等)

ArkTS状态管理装饰器V1版本详解

目录

ArkTS状态管理装饰器V1

组件定义

@Component

freezeWhenInactive11+

@Entry(通用)

EntryOptions10+

Component、Entry示例

@Reusable

组件状态管理

@State

a.b(this.object)形式调用,不会触发UI刷新

@Prop

State、Prop、Link示例

@Provide、@Consume

aliasName

重写@Provide

Provide、Consume示例

Observed、ObjectLink示例

页面状态存储

@LocalStorageProp

@LocalStorageLink

示例

自定义组件接收LocalStorage

其它状态管理

$$

$$示例

@Watch

Watch示例

@Track

Track示例


ArkTS状态管理装饰器V1

arkts早期提供给开发者使用的状态管理装饰器,对于嵌套类的观测存在诸多限制。在API12中为开发者提供了一套全新的状态管理V2(简称V2)。官方是希望后续用V2版本的装饰器取代V1的装饰器。实际上目前大部分的开发代码仍使用的是V1版本的装饰器。

装饰器类别 装饰器
组件内装饰器 @State、@Prop、@Link、@ObjectLink、@Provide、@Consume、@StorageProp、@StorageLink、@LocalStorageProp、@LocalStorageLink、@Watch
类相关装饰器 @Observed、@Track

组件定义

@Component

@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述UI,一个struct只能被一个@Component装饰。@Component可以接受一个可选的bool类型参数,用来冻结自定义组件(冻结的组件不会随@state变量更新变化UI)。

freezeWhenInactive11+

组件冻结选项。

名称 类型 必填 说明
freezeWhenInactive bool 是否开启组件冻结。
@Component({ freezeWhenInactive: true })
struct MyComponent {
}

@Entry(通用)

修饰@Component定义的自定义组件,将其作为入口组件。

入口组件:可以作为页面路由单独显示的,可以理解为一个完整的页面,无@Entry修饰的自定义组件只是部分页面,应用只能显示完整的页面,可以通过windowStage.loadContent方法决定挂载哪一个完整页面。

@Entry可以接受一个可选的LocalStorage的参数或者一个可选的EntryOptions参数。入参见

EntryOptions10+

命名路由跳转选项。

名称 类型 必填 说明
routeName string 表示作为命名路由页面的名字。
storage LocalStorage 页面级的UI状态存储。
useSharedStorage12+ boolean 是否使用LocalStorage.getShared()接口返回的LocalStorage实例对象,默认值false。

说明

当useSharedStorage设置为true,并且storage也被赋值时,useSharedStorage的值优先级更高

@Entry({ routeName : 'myPage' })
@Component
struct MyComponent {
}

Component、Entry示例

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
    }
    .height('100%')
    .width('100%')
  }
}

@Reusable

@Reusable适用自定义组件,与@Component结合使用,标记为@Reusable的自定义组件从组件树上被移除时,组件和其对应的JSView对象都会被放入复用缓存中,后续创建新自定义组件节点时,会复用缓存区中的节点,节约组件重新创建的时间。

复用组件的时候会执行aboutToReuse方法,该方法接收一个参数,参数上挂载了自定义组件被删除前的状态变量。

文档中心

组件状态管理

通过代理监听被装饰变量的变化来刷新组件的UI。

@State、@Prop、@Link装饰的变量可以监视基础变量的变化,以及复杂类型变量的单层变化,例如装饰对象时,可以监听到第一层属性指向的值的变化。当有嵌套时,是无法监听到里层属性的变化。

文档中心

@State

修饰自定义组件中的属性变量,变量变化会触发自定义组件的UI刷新。修饰的变量需要初始值

父组件调用自定义组件时可以通过同名入参传入子组件@State修饰的属性变量的值(会覆盖子组件中定义的初始值),但是父组件中的传入值变化不会导致子组件中的变量变化。如果想实现父到子的同步可以使用@Prop,想实现父子的完全同步可以使用@Link。

a.b(this.object)形式调用,不会触发UI刷新

<think>我们正在讨论ArkTS中的状态管理装饰器。用户的问题聚焦于为什么使用@State@Link时需要参数传递,而使用@Provide@Consume时不需要。我们需要基于提供的引用来解释原因。 引用[1]指出:@Provide@Consume用于与后代组件的双向数据同步,实现跨层级传递,摆脱了参数传递机制的束缚。而引用[2]则列出了ArkTS中各种状态管理装饰器,包括@State@Prop@Link@Provide/@Consume等。 分析: 1. @State@Link的使用场景: - @State组件内部的状态,通常用于组件内部的数据管理。如果子组件需要访问这个状态,则需要通过参数传递(通常配合@Prop@Link)将状态传递给子组件。 - @Link:用于父子组件之间的双向数据同步。父组件将一个状态变量通过参数传递给子组件,子组件@Link装饰器接收,这样两边的数据变化会同步。 因此,使用@State@Link时,我们必须在父组件中显式地将状态作为参数传递给子组件。例如: ```typescript // 父组件 @Component struct ParentComponent { @State message: string = 'Hello' build() { Column() { ChildComponent({ message: $message }) // 通过参数传递,$message表示传递的是引用(双向绑定) } } } // 子组件 @Component struct ChildComponent { @Link message: string // 通过@Link接收,与父组件@State建立双向绑定 build() { Text(this.message) .onClick(() => { this.message = 'Hi' }) // 修改会同步到父组件 } } ``` 2. @Provide@Consume的使用场景: - @Provide:在祖先组件中声明,它提供的状态可以被任意后代组件访问,而不需要通过参数逐层传递。 - @Consume:在后代组件中声明,用于消费祖先组件通过@Provide提供的状态,并且建立双向绑定。 因此,使用@Provide@Consume时,不需要通过组件的构造函数参数来传递,而是通过ArkTS框架内部建立的跨层级关联。例如: ```typescript // 祖先组件 @Component struct AncestorComponent { @Provide message: string = 'Hello' // 提供状态 build() { Column() { ChildComponent() // 不需要传递参数 } } } // 后代组件(可以是任意层级的子组件) @Component struct ChildComponent { @Consume message: string // 消费祖先提供的状态 build() { Text(this.message) .onClick(() => { this.message = 'Hi' }) // 修改会同步到祖先组件 } } ``` 原因总结: - @State@Link需要参数传递:因为它们的设计是用于父子组件之间的直接通信,所以必须通过显式的参数传递来建立关联。这种传递是逐级的,即只能从父组件传递给直接子组件。 - @Provide@Consume不需要参数传递:因为它们的设计目的是跨层级的状态同步,ArkTS框架在后台建立了祖先组件和后代组件之间的直接联系,因此无需通过中间组件一层层传递参数。 此外,引用[1]明确提到:@Provide@Consume“摆脱参数传递机制的束缚,实现跨层级传递”。 因此,我们可以这样回答用户:使用@State@Link时,状态传递仅限于父子组件之间,因此必须通过参数传递;而@Provide@Consume通过ArkTS框架内部机制实现了跨组件层级的直接绑定,因此无需参数传递。 生成相关问题: 1. 如何在ArkTS中实现跨组件层级的状态共享? 2. @Provide@Consume的工作原理是什么? 3. 在什么情况下应该使用@Link而不是@Consume? </think>在 ArkTS 中,`@State`/`@Link` 需要参数传递而 `@Provide`/`@Consume` 不需要的根本原因在于它们采用了**不同的状态管理机制**,主要体现在以下三方面: ### 1. 作用域与绑定机制不同 - **`@State`/`@Link`** 基于**父子组件的显式参数传递**机制: ```typescript // 父组件显式传递参数 struct Parent { @State message: string = "Hello" build() { Child({ msg: $message }) // 必须通过参数传递 } } // 子组件显式接收参数 struct Child { @Link msg: string // 必须通过参数绑定 } ``` 需要显式通过组件构造函数参数传递,形成父子组件之间的双向绑定[^2]。 - **`@Provide`/`@Consume`** 基于**组件树的隐式上下文注入**机制: ```typescript // 祖先组件提供状态 struct Ancestor { @Provide message: string = "Hello" // 自动注入上下文 build() { Descendant() // 无需参数传递 } } // 任意后代组件消费状态 struct Descendant { @Consume message: string // 自动从上下文获取 } ``` 通过 ArkTS 框架自动建立的跨组件上下文实现状态共享,无需参数传递[^1]。 ### 2. 层级穿透能力不同 - **`@State`/`@Link`** 只能实现**相邻层级**(父子组件)的状态同步。若需跨多层传递,必须在中间组件手动转发参数: ``` 父组件(参数) → 子组件(参数) → 孙组件 ``` - **`@Provide`/@Consume** 支持**任意层级穿透**,后代组件可直接访问祖先状态: ``` 祖先组件(@Provide) ↘ 子组件(无需传递) ↘ 孙组件(@Consume) ``` 有效避免了"逐层传递参数"的冗余代码[^1]。 ### 3. 设计目的不同 | 特性 | `@State`/`@Link` | `@Provide`/`@Consume` | |---------------------|----------------------------------|-----------------------------------| | **最佳场景** | 父子组件紧密耦合的状态同步 | 跨层级组件解耦的状态共享 | | **参数必要性** | 必须显式传递建立绑定 | 框架自动注入,无需传递 | | **代码侵入性** | 需修改中间组件接口 | 不修改中间组件 | | **典型应用** | 表单控件双向绑定 | 主题/用户信息等全局状态共享 | ### 总结 当需要**父子组件间直接通信**时,使用 `@State`/`@Link` 配合参数传递是合理选择;而当需要**跨多层组件共享状态**时,`@Provide`/`@Consume` 通过框架级上下文注入机制,避免了参数传递的繁琐过程,大幅提升代码可维护性[^1][^2]。 --- **相关问题**: 1. 在什么场景下应该优先选择 `@Provide`/`@Consume` 而不是 `@State`/`@Link`? 2. `@Provide`/`@Consume` 能否替代全局状态管理工具?有什么局限性? 3. 使用 `@Provide`/`@Consume` 时如何避免状态命名冲突? 4. `@Provide`/`@Consume` 的性能开销是否高于参数传递机制? 5. 在类组件和函数式组件中使用 `@Provide`/`@Consume` 有何区别?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值