当前位置:   article > 正文

鸿蒙笔记--装饰器

鸿蒙笔记--装饰器

       这一节主要了解一下鸿蒙里的装饰器,装饰器是一种特殊的语法结构,用于装饰类、结构体、方法以及变量;

1 @Component在鸿蒙(HarmonyOS)开发中扮演着重要角色,主要用于定义可重用的UI组件,主要作用:1)组件化:@Component装饰的struct表示该结构体具有组件化能力,能够成为一个独立的组件。这使得开发者可以将UI界面拆分成多个可复用的部分,提高代码的可维护性和复用性。
2)生命周期管理:被@Component装饰的组件可以调用组件的生命周期函数,如aboutToAppear(组件即将出现时回调)和aboutToDisappear(组件即将销毁前回调),从而进行资源管理和状态更新。3)UI绘制:每个被@Component装饰的组件都必须包含一个build()函数,该函数用于绘制组件的UI界面。这体现了声明式UI的核心思想,即数据驱动页面更新。

  1. import { Text, Button, Column } from '@ohos.agp.components';
  2. // 使用@Component装饰struct定义计数器组件
  3. @Component
  4. struct Counter {
  5. @State private count: number = 0;
  6. // build函数用于绘制组件的UI界面
  7. build() {
  8. Column() {
  9. // 显示计数值
  10. Text(`${this.count}`).fontSize(24)
  11. // 增加计数值的按钮
  12. Button('增加')
  13. .onClick(() => {
  14. this.count++; // 修改@State变量的值,触发UI更新
  15. })
  16. }
  17. }
  18. }
  19. @Entry
  20. @Component
  21. struct App {
  22. build() {
  23. Column() {
  24. // 使用Counter组件
  25. Counter()
  26. }
  27. }
  28. }

2 @Entry在鸿蒙中扮演着至关重要的角色,主要用于标识页面的入口组件。主要作用:1)页面入口标识:@Entry装饰的自定义组件会被视为当前页面的默认入口组件。在鸿蒙应用中,每个页面都是由一系列组件组合而成的,而@Entry装饰的组件则是这些组件的根节点,负责页面的初始化和呈现。2)预览支持:在使用预览器(如Previewer)进行页面预览时,@Entry装饰的组件会被首先创建并呈现,方便开发者在开发过程中实时查看页面的效果。3)组件树结构:在鸿蒙的组件化开发模式中,页面由多个组件构成,这些组件之间形成了一种树状结构。@Entry装饰的组件位于这棵树的根部,是页面加载和渲染的起点。

  1. import { TextInput, Button, Column } from '@ohos.agp.components';
  2. @Entry
  3. @Component
  4. struct LoginPage {
  5. // build函数用于绘制登录页面的UI界面
  6. build() {
  7. Column() {
  8. TextInput({ placeholder: '请输入用户名' })
  9. TextInput({ placeholder: '请输入密码', type: TextInputType.Password })
  10. // 登录按钮
  11. Button('登录')
  12. .onClick(() => {
  13. // 在这里处理登录逻辑,比如验证用户名和密码
  14. // ...
  15. })
  16. }
  17. }
  18. }

3 @State在鸿蒙中扮演着管理组件的状态信息的作用,主要作用:

  1. 1. 标记状态信息
  2. @State装饰器的主要作用是标记一个类或对象的属性为状态信息,表示该属性会随着时间的推移而发生变化。这些状态信息通常与组件的UI渲染相关联,当状态发生变化时,组件的UI也会相应地更新。
  3. 2. 自动同步状态
  4. 当一个属性被@State装饰后,该属性的值会被自动同步到应用的状态管理中。这意味着,当属性值发生变化时,应用的状态也会相应地更新,并且这种更新能够触发UI的重新渲染。这种机制有助于开发者在应用的不同组件之间共享状态数据,并且能够方便地观察和响应这些状态的变化。
  5. 3. 响应式编程
  6. @State装饰器是实现响应式编程的关键之一。在鸿蒙开发中,响应式编程是一种重要的编程范式,它允许开发者以声明式的方式编写代码,并通过状态的变化来驱动UI的更新。@State装饰器使得开发者可以轻松地定义状态变量,并在状态变化时自动触发UI的更新,从而简化了UI更新的逻辑。
  7. 4. 私有性和初始化
  8. @State装饰的变量是私有的,只能从组件内部访问。这有助于封装组件的内部状态,防止外部代码直接修改状态变量,从而保证了组件的封装性和安全性。此外,@State装饰的变量必须初始化,不能为空。这确保了状态变量在使用前已经有一个明确的初始值,避免了因未初始化而导致的潜在问题。
  9. 5. 支持多种数据类型
  10. @State装饰器可以作用到多种数据类型上,包括基本数据类型(如numberstringboolean等)和复杂数据类型(如Objectclass、array等)。这使得开发者可以根据需要灵活地定义状态变量的类型,并在状态变化时更新相应的UI元素。
  11. 6. 生命周期管理
  12. @State装饰的变量生命周期与其所属自定义组件的生命周期相同。当组件被销毁时,其内部的状态变量也会被销毁,从而避免了内存泄漏等问题。

4 @Prop在鸿蒙中主要用于定义组件的属性,并确保组件属性与父组件数据源之间的同步关系。主要作用:

  1. 1. 定义组件属性
  2. @Prop装饰器用于在子组件中定义那些需要从父组件接收的属性。这些属性可以是基本数据类型(如stringnumberboolean等),也可以是枚举类型(enum),但不支持any类型,也不允许使用undefinednull作为初始值。在父组件中,通过传递给子组件的构造参数来初始化这些@Prop装饰的属性。
  3. 2. 单向同步
  4. @Prop装饰的变量与父组件之间建立的是单向同步关系。这意味着,当父组件中的数据源发生变化时,与之相关的@Prop装饰的变量会自动更新,以保持与父组件数据的一致性。然而,子组件中对@Prop装饰的变量所做的修改不会同步回父组件。这种单向同步机制有助于维护父子组件之间的数据流向清晰,避免数据混乱。
  5. 3. 初始化与修改
  6. @Prop装饰的变量允许在子组件中进行本地初始化和修改。但是,需要注意的是,如果父组件中的数据源在子组件本地修改之后发生了变化,那么子组件本地对@Prop装饰的变量所做的修改将被覆盖。这是因为@Prop装饰的变量本质上是父组件数据源的副本,它们之间的同步关系是单向的。
  7. 4. 变量类型与深拷贝
  8. @Prop装饰的变量在父子组件同步过程中会进行深拷贝。这意味着,除了基本类型、MapSetDateArray等特定类型外,其他类型的数据在拷贝过程中可能会丢失其原有的类型信息。因此,在使用@Prop装饰器时,需要注意数据类型的问题,以避免因类型不匹配或丢失而导致的错误。
  1. @Component
  2. struct ChildComponent {
  3. @Prop childCount: number;
  4. build() {
  5. Text(`子组件计数: ${this.childCount}`).fontSize(24)
  6. }
  7. }
  8. @Entry
  9. @Component
  10. struct ParentComponent {
  11. @State parentCount: number = 0;
  12. build() {
  13. Column() {
  14. Text(`父组件计数: ${this.parentCount}`).fontSize(24)
  15. Button('增加计数')
  16. .onClick(() => {
  17. this.parentCount++;
  18. })
  19. // 将parentCount传递给子组件的childCount
  20. ChildComponent({ childCount: this.parentCount })
  21. }
  22. }
  23. }

5 @Provide在鸿蒙中主要用于实现跨层级组件间的数据共享和状态同步,一般与Consume配合使用,主要作用:

  1. 1. 数据提供与共享
  2. @Provide装饰的变量被视为在组件树中向上提供的状态变量,这些变量自动对其所有后代组件可用。这意味着,在祖先组件中通过@Provide装饰的变量,可以被其所有后代组件通过@Consume装饰器来访问和绑定,从而实现跨层级的数据共享。
  3. 2. 跨层级状态同步
  4. 不同于@State@Link等装饰器,@Provide@Consume的组合允许在多层级的父子组件之间传递和同步状态。这种机制摆脱了参数传递机制的束缚,使得开发者可以更加方便地在复杂的组件树中管理和同步状态。
  5. 3. 双向数据同步
  6. 虽然@Provide本身主要用于数据提供,但与其配合使用的@Consume装饰器能够实现数据的双向同步。当@Provide装饰的变量在祖先组件中被更新时,所有绑定了该变量的后代组件也会自动更新其UI,反之亦然(尽管在实际应用中,后代组件通常不会直接修改@Provide的变量,而是通过事件或其他机制来请求祖先组件更新状态)。
  7. 4. 变量别名与绑定
  8. @Provide装饰器允许开发者为提供的变量指定别名。这样,后代组件在通过@Consume装饰器绑定变量时,可以使用相同的变量名或别名来实现绑定。这种机制增加了灵活性,允许开发者在复杂的组件树中更容易地管理和识别状态变量。
  9. 5. 初始化与类型要求
  10. @Provide装饰的变量必须指定初始值,这是确保状态变量在组件树中有效传递的前提。同时,@Provide@Consume绑定的变量类型必须相同,以保证数据的正确性和一致性。
  1. @Entry
  2. @Component
  3. struct CompA {
  4. @Provide reviewVotes: number = 0;
  5. build() {
  6. // ...
  7. }
  8. }
  9. @Component
  10. struct CompD {
  11. @Consume reviewVotes: number;
  12. build() {
  13. // 使用reviewVotes变量来更新UI
  14. }
  15. }

6 @Observed 和 @ObjectLink 装饰器通常一起使用,以实现对象属性变化的观察和UI的自动更新。

  1. 1. 属性变化观察
  2. @Observed装饰的类(class)会被自动观察其属性的变化。当类中的某个属性被修改时,鸿蒙框架能够感知到这种变化,并据此进行相应的响应。这种机制使得开发者可以方便地实现响应式编程,即根据数据的变化自动更新UI或其他状态。
  3. 2. 双向数据同步支持
  4. 虽然@Observed本身并不直接实现双向数据同步,但它与@ObjectLink等装饰器配合使用,可以支持在父子组件之间进行双向数据同步。在父组件中,使用@Observed装饰的类实例可以被传递给子组件,并通过@ObjectLink在子组件中接收,从而建立父子组件之间的双向数据绑定关系。
  5. 3. 嵌套对象与数组的支持
  6. @Observed不仅支持对简单类型属性的观察,还支持对嵌套对象或数组等复杂数据结构的观察。这意味着,即使数据结构嵌套多层,只要使用@Observed进行装饰,鸿蒙框架都能够感知到其内部属性的变化,并作出相应的响应。
  7. 4. 改变类原型链
  8. 需要注意的是,使用@Observed装饰类会改变其原始的原型链。这种改变是为了实现属性的观察与响应机制,但也可能带来一些潜在的问题。因此,在使用@Observed时,需要谨慎考虑其可能带来的影响,并避免与其他类装饰器同时装饰同一个类,以免发生冲突。
  1. @Observed
  2. class Person {
  3. public name: string;
  4. public age: number;
  5. constructor(name: string, age: number) {
  6. this.name = name;
  7. this.age = age;
  8. }
  9. }
  10. // ParentComponent.ts
  11. @Entry
  12. @Component
  13. struct ParentComponent {
  14. @State person: Person = new Person('Alice', 30);
  15. build() {
  16. // ... 传递person实例给子组件
  17. }
  18. }
  19. // ChildComponent.ts
  20. @Component
  21. struct ChildComponent {
  22. @ObjectLink person: Person;
  23. build() {
  24. // 使用person实例的属性来更新UI
  25. }
  26. }

7 @Builder在鸿蒙中提供了一种更轻量的UI元素复用机制。主要作用:

  1. UI元素复用:通过@Builder装饰的函数,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里进行调用,从而减少代码的冗余,提高开发效率。
  2. 封装复杂性:对于复杂的UI布局,使用@Builder可以将布局逻辑封装在自定义构建函数中,使得build方法更加简洁明了。
  3. 支持组件内和全局使用:@Builder装饰的函数既可以在自定义组件内部定义和使用,也可以定义为全局函数,供整个应用使用。
  1. @Entry
  2. @Component
  3. struct MyComponent {
  4. build() {
  5. Column() {
  6. // 调用自定义构建函数
  7. this.myCustomBuilder()
  8. }
  9. }
  10. @Builder
  11. myCustomBuilder() {
  12. Row() {
  13. Text('Hello, Builder!')
  14. }
  15. }
  16. }

8 @Extend在ArkUI框架中用于扩展原生组件的样式和行为,主要作用:

  1. 行为封装:除了样式外,@Extend还可以封装组件的私有属性、私有事件和预定义的方法,使得组件的行为更加模块化和可重用。
  2. 全局定义:@Extend装饰的方法需要在全局范围内定义,不支持在组件内部定义,这有助于保持代码的整洁和一致性。
  3. 参数支持:@Extend装饰的方法支持参数,这使得它可以根据不同的需求动态地应用不同的样式或行为。
  1. // 定义扩展样式
  2. @Extend(Text)
  3. function fancyText(fontSize: number, fontColor: Color) {
  4. .fontSize(fontSize)
  5. .fontColor(fontColor)
  6. .fontWeight(FontWeight.Bold)
  7. .fontStyle(FontStyle.Italic)
  8. }
  9. // 在组件中使用扩展样式
  10. @Entry
  11. @Component
  12. struct MyComponent {
  13. @State label: string = 'Hello, Extend!';
  14. build() {
  15. Column() {
  16. // 应用扩展样式
  17. Text(this.label)
  18. .fancyText(24, Color.Red)
  19. .margin({ top: 10 })
  20. }
  21. }
  22. }

9 @CustomDialog在ArkUI框架中用于创建自定义对话框,主要作用:

  1. 自定义内容:@CustomDialog允许开发者在对话框中显示任何类型的内容,如文本、图像、表单、按钮等,从而满足多样化的交互需求。
  2. 高度可配置:通过@CustomDialog装饰的自定义对话框,开发者可以自定义对话框的标题、消息、按钮、图标等属性,以及对话框的样式和布局。
  3. 数据交互:自定义对话框还可以作为数据交互的桥梁,通过用户输入或选择的信息进行处理,并展示需要的信息给用户。
  4. 提升用户体验:@CustomDialog可以帮助开发者在用户操作过程中快速展示信息或选项,减少操作繁琐度和时间成本,从而提升用户体验。
  1. @CustomDialog
  2. struct CustomDialogExample {
  3. // 自定义对话框的控制器
  4. controller: CustomDialogController
  5. build() {
  6. Column() {
  7. Text('我是内容')
  8. .fontSize(20)
  9. .margin({ top: 10, bottom: 10 })
  10. // 添加按钮,并绑定点击事件
  11. Flex({ justifyContent: FlexAlign.SpaceAround }) {
  12. Button('cancel')
  13. .onClick(() => {
  14. this.controller.close()
  15. if (this.cancel) {
  16. this.cancel()
  17. }
  18. })
  19. .backgroundColor(0xffffff)
  20. .fontColor(Color.Black)
  21. Button('confirm')
  22. .onClick(() => {
  23. this.controller.close()
  24. if (this.confirm) {
  25. this.confirm()
  26. }
  27. })
  28. .backgroundColor(0xffffff)
  29. .fontColor(Color.Red)
  30. }
  31. .margin({ bottom: 10 })
  32. }
  33. }
  34. }
  1. // 在页面组件中使用自定义对话框
  2. @Entry
  3. @Component
  4. struct CustomDialogUser {
  5. dialogController: CustomDialogController = new CustomDialogController({
  6. builder: CustomDialogExample({
  7. // 可以传入回调函数作为cancel和confirm属性的值
  8. cancel: () => {
  9. console.info('Callback when the cancel button is clicked')
  10. },
  11. confirm: () => {
  12. console.info('Callback when the confirm button is clicked')
  13. }
  14. })
  15. })
  16. build() {
  17. Column() {
  18. Button('click me')
  19. .onClick(() => {
  20. this.dialogController.open()
  21. })
  22. .width('100%')
  23. .margin({ top: 5 })
  24. }
  25. }
  26. }

10 @Watch在ArkUI框架中主要用于监听状态变量的变化。当被@Watch装饰的状态变量发生变化时,会自动调用指定的回调函数,从而允许开发者执行相应的逻辑处理。主要作用:

  1. 状态监听:@Watch允许开发者监听指定状态变量的值的变化,当值发生变化时,执行特定的回调函数。
  2. 数据响应:在组件或页面的开发中,@Watch用于实现数据的响应式更新。当数据变化时,能够自动触发UI的重新渲染,保证界面与数据的同步。
  3. 性能优化:通过细粒度地控制哪些状态变量的变化需要触发UI更新,可以避免不必要的渲染,从而优化应用的性能。
  1. @Component
  2. struct TotalView {
  3. @Prop @Watch('onCountUpdated') count: number;
  4. @State total: number = 0;
  5. // @Watch 回调
  6. onCountUpdated(propName: string): void {
  7. this.total += this.count;
  8. }
  9. build() {
  10. Text(`Total: ${this.total}`)
  11. }
  12. }
  13. @Entry
  14. @Component
  15. struct CountModifier {
  16. @State count: number = 0;
  17. build() {
  18. Column() {
  19. Button('add to basket')
  20. .onClick(() => {
  21. this.count++
  22. })
  23. TotalView({ count: this.count })
  24. }
  25. }
  26. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/934683
推荐阅读
相关标签
  

闽ICP备14008679号