ToB企服应用市场:ToB评测及商务社交产业平台

标题: HarmonyOS鸿蒙学习基础篇 - 自界说组件(一) [打印本页]

作者: tsx81429    时间: 2024-6-22 13:02
标题: HarmonyOS鸿蒙学习基础篇 - 自界说组件(一)
媒介

    在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为体系组件,由开辟者界说的称为自界说组件。在举行 UI 界面开辟时,通常不是简单的将体系组件举行组合使用,而是必要思量代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自界说组件是不可或缺的本领。
自界说组特点:

根本用法:

  1. @Component
  2. struct HelloComponent {
  3.   @State message: string = 'Hello, World!';
  4.   build() {
  5.     // HelloComponent自定义组件组合系统组件Row和Text
  6.     Row() {
  7.       Text(this.message)
  8.         .onClick(() => {
  9.           // 状态变量message的改变驱动UI刷新,UI从'Hello, World!'刷新为'Hello, ArkUI!'
  10.           this.message = 'Hello, ArkUI!';
  11.         })
  12.     }
  13.   }
  14. }
复制代码
  HelloComponent可以在其他自界说组件中的build()函数中多次创建,实现自界说组件的重用。
  
  1. @Entry
  2. @Component
  3. struct ParentComponent {
  4.   build() {
  5.     Column() {
  6.       Text('ArkUI message')
  7.       HelloComponent({ message: 'Hello, World!' });
  8.       Divider()
  9.       HelloComponent({ message: '你好!' });
  10.     }
  11.   }
  12. }
复制代码
  以上代码写入一个arkts文件中,并设置对应的字体样式,如下:
  
  1. @Component
  2. struct HelloComponent {
  3.   @State message: string = 'Hello, World!';
  4.   build() {
  5.     // HelloComponent自定义组件组合系统组件Row和Text
  6.     Row() {
  7.       Text(this.message)
  8.         .height(50)
  9.         .width(200)
  10.         .fontSize(30)
  11.         .onClick(() => {
  12.           // 状态变量message的改变驱动UI刷新,UI从'Hello, World!'刷新为'Hello, ArkUI!'
  13.           this.message = 'Hello, ArkUI!';
  14.         })
  15.     }
  16.   }
  17. }
  18. @Entry
  19. @Component
  20. struct ParentComponent {
  21.   build() {
  22.     Column() {
  23.       Text('ArkUI message')
  24.         .height(100)
  25.         .fontSize(50)
  26.         .fontWeight(FontWeight.Bold)
  27.       HelloComponent({ message: 'Hello, World!' });
  28.       Divider()
  29.       HelloComponent({ message: '你好!' });
  30.     }
  31.   }
  32. }
复制代码
  预览如下,点击“Hello,World!”或者“你好”都会改变为“Hello, ArkUI!”做到了自界说组件复用。
   


根本结构

1.struct

自界说组件基于struct实现,struct + 自界说组件名 + {...}的组合构成自界说组件,不能有继续关系。对于struct的实例化,可以省略new。
注意:自界说组件名、类名、函数名不能和体系组件名相同。
2.@Component

@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的本领,必要实现build方法描述UI,一个struct只能被一个@Component装饰。
@Component
struct MyComponent {
}

注意:从API version 9开始,该装饰器支持在ArkTS卡片中使用。
3.build()函数

build()函数用于界说自界说组件的声明式UI描述,自界说组件必须界说build()函数。
@Component
struct MyComponent {
  build() {
  }
}
4.@Entry

@Entry装饰的自界说组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自界说组件。@Entry可以接受一个可选的LocalStorage的参数。
@Entry
@Component
struct MyComponent {
}
注意:从API version 9开始,该装饰器支持在ArkTS卡片中使用。

函数变量

自界说组件除了必须要实现build()函数外,还可以实现其他成员函数,成员函数具有以下束缚:
自界说组件可以包含成员变量,成员变量具有以下束缚:
参数规定

从上文的示例中,我们已经了解到,可以在build方法或者@Builder装饰的函数里创建自界说组件,在创建自界说组件的过程中,根据装饰器的规则来初始化自界说组件的参数。
  1. @Component
  2. struct MyComponent {
  3.   private countDownFrom: number = 0;
  4.   private color: Color = Color.Blue;
  5.   build() {
  6.   }
  7. }
  8. @Entry
  9. @Component
  10. struct ParentComponent {
  11.   private someColor: Color = Color.Pink;
  12.   build() {
  13.     Column() {
  14.       // 创建MyComponent实例,并将创建MyComponent成员变量countDownFrom初始化为10,将成员变量color初始化为this.someColor
  15.       MyComponent({ countDownFrom: 10, color: this.someColor })
  16.     }
  17.   }
  18. }
复制代码


build()函数

全部声明在build()函数的语言,我们统称为UI描述,UI描述必要遵循以下规则:
  1. @Entry
  2. @Component
  3. struct MyComponent {
  4.   build() {
  5.     // 根节点唯一且必要,必须为容器组件
  6.     Row() {
  7.       ChildComponent()
  8.     }
  9.   }
  10. }
  11. @Component
  12. struct ChildComponent {
  13.   build() {
  14.     // 根节点唯一且必要,可为非容器组件
  15.     Image('test.jpg')
  16.   }
  17. }
复制代码

build() {
  // 反例:不允许声明当地变量
  let a: number = 1;
}
build() {
  // 反例:不允许console.info
  console.info('print debug log');
}
build() {
  // 反例:不允许当地作用域
  {
    ...
  }
}
  1. @Component
  2. struct ParentComponent {
  3.   doSomeCalculations() {
  4.   }
  5.   calcTextValue(): string {
  6.     return 'Hello World';
  7.   }
  8.   @Builder doSomeRender() {
  9.     Text(`Hello World`)
  10.   }
  11.   build() {
  12.     Column() {
  13.       // 反例:不能调用没有用@Builder装饰的方法
  14.       this.doSomeCalculations();
  15.       // 正例:可以调用
  16.       this.doSomeRender();
  17.       // 正例:参数可以为调用TS方法的返回值
  18.       Text(this.calcTextValue())
  19.     }
  20.   }
  21. }
复制代码


  1. build() {
  2.   Column() {
  3.     // 反例:不允许使用switch语法
  4.     switch (expression) {
  5.       case 1:
  6.         Text('...')
  7.         break;
  8.       case 2:
  9.         Image('...')
  10.         break;
  11.       default:
  12.         Text('...')
  13.         break;
  14.     }
  15.   }
  16. }
复制代码

build() {
  Column() {
    // 反例:不允许使用表达式
    (this.aVar > 10) ? Text('...') : Image('...')
  }
}
通用样式

   自界说组件通过“.”链式调用的情势设置通用样式。
  
  1. @Component
  2. struct MyComponent2 {
  3.   build() {
  4.     Button(`Hello World`)
  5.   }
  6. }
  7. @Entry
  8. @Component
  9. struct MyComponent {
  10.   build() {
  11.     Row() {
  12.       MyComponent2()
  13.         .width(200)
  14.         .height(300)
  15.         .backgroundColor(Color.Red)
  16.     }
  17.   }
  18. }
复制代码
    以上自界说组件预览结果如下,可以看到ArkUI给自界说组件设置样式时,相当于给MyComponent2套了一个不可见的容器组件,而这些样式是设置在容器组件上的,而非直接设置给MyComponent2的Button组件。通过渲染结果我们可以很清楚的看到,配景颜色赤色并没有直接见效在Button上,而是见效在Button所处的开辟者不可见的容器组件上。

生命周期

  自界说组件和页面的关系:
页面生命周期,即被@Entry装饰的组件生命周期,提供以下生命周期接口:
组件生命周期,即一样平常用@Component装饰的自界说组件的生命周期,提供以下生命周期接口:
   生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(首页)生命周期。
   

      必要注意的是,部分生命周期回调函数仅对@Entry修饰的自界说组件见效,它们分别是:onPageShow、onPageHide、onBackPress。根据上面的流程图,我们从自界说组件的初始创建、重新渲染和删除来详细解释。 
   自界说组件的创建和渲染流程

  1. build() {
  2.   ...
  3.   this.observeComponentCreation(() => {
  4.     Button.create();
  5.   })
  6.   this.observeComponentCreation(() => {
  7.     Text.create();
  8.   })
  9.   ...
  10. }
复制代码

   当应用在配景启动时,此时应用历程并没有销毁,以是仅必要执行onPageShow。
  自界说组件重新渲染 

    当变乱句柄被触发(比如设置了点击变乱,即触发点击变乱)改变了状态变量时,或者LocalStorage / AppStorage中的属性更改,并导致绑定的状态变量更改其值时:
自界说组件的删除

   如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:
     不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自界说组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自界说组件的垃圾回收。
 以下示例展示了生命周期的调用时机:
  1. import router from '@ohos.router';
  2. @Entry
  3. @Component
  4. struct MyComponent {
  5.   @State showChild: boolean = true;
  6.   // 只有被@Entry装饰的组件才可以调用页面的生命周期
  7.   onPageShow() {
  8.     console.info('Index onPageShow');
  9.   }
  10.   // 只有被@Entry装饰的组件才可以调用页面的生命周期
  11.   onPageHide() {
  12.     console.info('Index onPageHide');
  13.   }
  14.   // 只有被@Entry装饰的组件才可以调用页面的生命周期
  15.   onBackPress() {
  16.     console.info('Index onBackPress');
  17.   }
  18.   // 组件生命周期
  19.   aboutToAppear() {
  20.     console.info('MyComponent aboutToAppear');
  21.   }
  22.   // 组件生命周期
  23.   aboutToDisappear() {
  24.     console.info('MyComponent aboutToDisappear');
  25.   }
  26.   build() {
  27.     Column() {
  28.       // this.showChild为true,创建Child子组件,执行Child aboutToAppear
  29.       if (this.showChild) {
  30.         Child()
  31.       }
  32.       // this.showChild为false,删除Child子组件,执行Child aboutToDisappear
  33.       Button('create or delete Child').onClick(() => {
  34.         this.showChild = false;
  35.       })
  36.       // push到Page2页面,执行onPageHide
  37.       Button('push to next page')
  38.         .onClick(() => {
  39.           router.pushUrl({ url: 'pages/Page2' });
  40.         })
  41.     }
  42.   }
  43. }
  44. @Component
  45. struct Child {
  46.   @State title: string = 'Hello World';
  47.   // 组件生命周期
  48.   aboutToDisappear() {
  49.     console.info('[lifeCycle] Child aboutToDisappear')
  50.   }
  51.   // 组件生命周期
  52.   aboutToAppear() {
  53.     console.info('[lifeCycle] Child aboutToAppear')
  54.   }
  55.   build() {
  56.     Text(this.title).fontSize(50).onClick(() => {
  57.       this.title = 'Hello ArkUI';
  58.     })
  59.   }
  60. }
复制代码

   以上示例中,Index页面包含两个自界说组件,一个是被@Entry装饰的MyComponent,也是页面的入口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只有@Entry装饰的节点才可以使页面级别的生命周期方法见效,以是MyComponent中声明了当前Index页面的页面生命周期函数。MyComponent和其子组件Child也同时也声明了组件的生命周期函数。
退出应用,执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4