diff --git a/zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md b/zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md index ab92bc000665ebbaa9b0cccb0bff61df1ff8bc96..075dfa40213d997a7cd56171f729844e5d6656a2 100644 --- a/zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md +++ b/zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md @@ -72,4 +72,64 @@ struct IndexPage { } ``` -![hello](figures/hello.PNG) \ No newline at end of file +![hello](figures/hello.PNG) + +## 自定义组件成员变量初始化的方式与约束 + +组件的成员变量可以通过两种方式初始化: + +- 本地初始化: + + ```ts + @State counter: Counter = new Counter() + ``` +- 在构造组件时通过构造参数初始化: + + ```ts + MyComponent({counter: $myCounter}) + ``` + +具体允许哪种方式取决于状态变量的装饰器: + +| 装饰器类型 | 本地初始化 | 通过构造函数参数初始化 | +| ------------ | ----- | ----------- | +| @State | 必须 | 可选 | +| @Prop | 禁止 | 必须 | +| @Link | 禁止 | 必须 | +| @StorageLink | 必须 | 禁止 | +| @StorageProp | 必须 | 禁止 | +| @Provide | 必须 | 可选 | +| @Consume | 禁止 | 禁止 | +| @ObjectLink | 禁止 | 必须 | +| 常规成员变量 | 推荐 | 可选 | + +从上表中可以看出: + +- @State变量需要本地初始化,初始化的值可以被构造参数覆盖。 + +- @Prop和@Link变量必须且仅通过构造函数参数进行初始化。 + +通过构造函数方法初始化成员变量,需要遵循如下规则: + +| 从父组件中的变量(下)到子组件中的变量(右) | @State | @Link | @Prop | 常规变量 | +| ---------------------- | ------ | ----- | ----- | ---- | +| @State | 不允许 | 允许 | 允许 | 允许 | +| @Link | 不允许 | 允许 | 不推荐 | 允许 | +| @Prop | 不允许 | 不允许 | 允许 | 允许 | +| @StorageLink | 不允许 | 允许 | 不允许 | 允许 | +| @StorageProp | 不允许 | 不允许 | 不允许 | 允许 | +| 常规变量 | 允许 | 不允许 | 不允许 | 允许 | + +从上表中可以看出: + +- 父组件的常规变量可以用于初始化子组件的@State变量,但不能用于初始化@Link或@Prop变量。 + +- 父组件的@State变量可以初始化子组件的@Prop、@Link(通过$)或常规变量,但不能初始化子组件的@State变量。 + +- 父组件的@Link变量可以初始化子组件的@Link或常规变量。但是初始化子组件的@State成员是语法错误,此外不建议初始化@Prop。 + +- 父组件的@Prop变量可以初始化子组件的常规变量或@Prop变量,但不能初始化子组件的@State或@Link变量。 + +- @StorageLink和@StorageProp不允许由父组件中传递到子组件。 + +- 除了上述规则外,还需要遵循TS的强类型规则。 \ No newline at end of file diff --git a/zh-cn/application-dev/ui/Readme-CN.md b/zh-cn/application-dev/ui/Readme-CN.md index 2799e731ee9fdfa6ba429d66f9c49835281f0d41..ed72f79bff42a7a00559edc1703d06311809c50e 100755 --- a/zh-cn/application-dev/ui/Readme-CN.md +++ b/zh-cn/application-dev/ui/Readme-CN.md @@ -3,23 +3,14 @@ - [方舟开发框架(ArkUI)概述](arkui-overview.md) - UI开发(基于ArkTS的声明式开发范式) - [概述](ui-ts-overview.md) - - 框架说明 - - 文件组织 - - [目录结构](ts-framework-directory.md) - - [应用代码文件访问规则](ts-framework-file-access-rules.md) - - 深入理解组件化 - - [自定义组件初始化](ts-custom-component-initialization.md) - - [自定义组件生命周期回调函数](ts-custom-component-lifecycle-callbacks.md) - - [组件创建和重新初始化示例](ts-component-creation-re-initialization.md) - + - [声明式UI开发指导](ui-ts-developing-intro.md) - 声明式开发实例 - [创建简单视图](ui-ts-creating-simple-page.md) - - 构建实例 + - 构建完整实例 - [构建食物数据模型](ui-ts-building-data-model.md) - [构建食物列表List布局](ui-ts-building-category-list-layout.md) - [构建食物分类Grid布局](ui-ts-building-category-grid-layout.md) - - [页面跳转与数据传递](ui-ts-page-redirection-data-transmission.md) - + - [页面跳转与数据传递](ui-ts-page-redirection-data-transmission.md) - 添加闪屏动画 - [绘制图像](ui-ts-drawing-feature.md) - [添加动画效果](ui-ts-animation-feature.md) @@ -33,8 +24,9 @@ - [栅格布局](ui-ts-layout-grid-container.md) - [栅格布局(新)](ui-ts-layout-grid-container-new.md) - [媒体查询](ui-ts-layout-mediaquery.md) - - [Web组件开发](ui-ts-components-web.md) - - [性能提升的推荐方法](ts-performance-improvement-recommendation.md) + - [自定义组件的生命周期](ui-ts-custom-component-lifecycle-callbacks.md) + - [Web组件开发指导](ui-ts-components-web.md) + - [性能提升的推荐方法](ui-ts-performance-improvement-recommendation.md) - UI开发(兼容JS的类Web开发范式) - [概述](ui-js-overview.md) - 框架说明 diff --git a/zh-cn/application-dev/ui/ts-component-creation-re-initialization.md b/zh-cn/application-dev/ui/ts-component-creation-re-initialization.md deleted file mode 100644 index 86db59447ccb15bad9579553a1eef2e03e143d23..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-creation-re-initialization.md +++ /dev/null @@ -1,97 +0,0 @@ -# 组件创建和重新初始化 - -## 初始创建和渲染 - -1. 创建父组件ParentComp; - -2. 本地初始化ParentComp的状态变量isCountDown; - -3. 执行ParentComp的build函数; - -4. 创建Column内置组件; - 1. 创建Text内置组件,设置其文本展示内容,并将Text组件实例添加到Column中; - 2. 判断if条件,创建true分支上的组件; - 1. 创建Image内置组件,并设置其图片源地址; - 2. 使用给定的构造函数创建TimerComponent; - 1. 创建TimerComponent对象; - 2. 本地初始化成员变量初始值; - 3. 使用TimerComponent构造函数提供的参数更新成员变量的值; - 4. 执行TimerComponent的aboutToAppear函数; - 5. 执行TimerComponent的build函数,创建相应的UI描述结构; - 3. 创建Button内置组件,设置相应的内容。 - - -## 状态更新 - -用户单击按钮时: - -1. ParentComp的isCountDown状态变量的值更改为false; - -2. 执行ParentComp的build函数; - -3. Column内置组件会被框架重用并执行重新初始化; - -4. Column的子组件会重用内存中的对象,但会进行重新初始化; - 1. Text内置组件会被重用,但使用新的文本内容进行重新初始化; - 2. 判断if条件,使用false分支上的组件; - 1. 原来true分支上的组件不在使用,这些组件会进行销毁; - 1. 创建的Image内置组件实例进行销毁; - 2. TimerComponent组件实例进行销毁,aboutToDisappear函数被调用; - 2. 创建false分支上的组件; - 1. 创建Image内置组件,并设置其图片源地址; - 2. 使用给定的构造函数重新创建TimerComponent; - 3. 新创建的TimerComponent进行初始化,并调用aboutToAppear函数和build函数。 - 3. Button内置组件会被重用,但使用新的图片源地址。 - - -## 示例 - -```ts -// xxx.ets -@Entry -@Component -struct ParentComp { - @State isCountDown: boolean = true - build() { - Column() { - Text(this.isCountDown ? 'Count Down' : 'Stopwatch') - if (this.isCountDown) { - Image($r("app.media.countdown")).width(200).height(200) - TimerComponent({counter: 10, changePerSec: -1, showInColor: Color.Red}) - } else { - Image($r("app.media.stopwatch")).width(200).height(200) - TimerComponent({counter: 0, changePerSec: +1, showInColor: Color.Black }) - } - Button(this.isCountDown ? 'Switch to Stopwatch' : 'Switch to Count Down') - .onClick(() => {this.isCountDown = !this.isCountDown}) - } - } -} - -// Manage and display a count down / stop watch timer -@Component -struct TimerComponent { - @State counter: number = 0 - private changePerSec: number = -1 - private showInColor: Color = Color.Black - private timerId : number = -1 - - build() { - Text(`${this.counter}sec`) - .fontColor(this.showInColor) - } - - aboutToAppear() { - this.timerId = setInterval(() => {this.counter += this.changePerSec}, 1000) - } - - aboutToDisappear() { - if (this.timerId > 0) { - clearTimeout(this.timerId) - this.timerId = -1 - } - } -} -``` - -![](figures/zh-cn_image_0000001118642023.gif) \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ts-custom-component-initialization.md b/zh-cn/application-dev/ui/ts-custom-component-initialization.md deleted file mode 100644 index 3858d3032581956f10904912e28012e72b1eb451..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-custom-component-initialization.md +++ /dev/null @@ -1,125 +0,0 @@ -# 自定义组件成员变量初始化 - -组件的成员变量可以通过两种方式初始化: - - -- 本地初始化,例如: - ```ts - @State counter: Counter = new Counter() - ``` - -- 在构造组件时通过构造参数初始化,例如: - ```ts - MyComponent({counter: $myCounter}) - ``` - - -具体允许哪种方式取决于[状态变量](../quick-start/arkts-state-mgmt-concepts.md)的装饰器: - - -| 装饰器类型 | 本地初始化 | 通过构造函数参数初始化 | -| ------------ | ----- | ----------- | -| @State | 必须 | 可选 | -| @Prop | 禁止 | 必须 | -| @Link | 禁止 | 必须 | -| @StorageLink | 必须 | 禁止 | -| @StorageProp | 必须 | 禁止 | -| @Provide | 必须 | 可选 | -| @Consume | 禁止 | 禁止 | -| @ObjectLink | 禁止 | 必须 | -| 常规成员变量 | 推荐 | 可选 | - - -从上表中可以看出: - - -- @State变量需要本地初始化,初始化的值可以被构造参数覆盖; - -- @Prop和@Link变量必须且仅通过构造函数参数进行初始化。 - - -通过构造函数方法初始化成员变量,需要遵循如下规则: - - -| 从父组件中的变量(下)到子组件中的变量(右) | @State | @Link | @Prop | 常规变量 | -| ---------------------- | ------ | ----- | ----- | ---- | -| @State | 不允许 | 允许 | 允许 | 允许 | -| @Link | 不允许 | 允许 | 不推荐 | 允许 | -| @Prop | 不允许 | 不允许 | 允许 | 允许 | -| @StorageLink | 不允许 | 允许 | 不允许 | 允许 | -| @StorageProp | 不允许 | 不允许 | 不允许 | 允许 | -| 常规变量 | 允许 | 不允许 | 不允许 | 允许 | - - -从上表中可以看出: - - -- 父组件的常规变量可以用于初始化子组件的@State变量,但不能用于初始化@Link或@Prop变量。 - -- 父组件的@State变量可以初始化子组件的@Prop、@Link(通过$)或常规变量,但不能初始化子组件的@State变量。 - -- 父组件的@Link变量可以初始化子组件的@Link或常规变量。但是初始化子组件的@State成员是语法错误,此外不建议初始化@prop。 - -- 父组件的@Prop变量可以初始化子组件的常规变量或@Prop变量,但不能初始化子组件的@State或@Link变量。 - -- @StorageLink和@StorageProp不允许由父组件中传递到子组件。 - -- 除了上述规则外,还需要遵循TS的强类型规则。 - - -## 示例 - -```ts -// xxx.ets -class ClassA { - public a:number - constructor(a: number) { - this.a = a - } -} -@Entry -@Component -struct Parent { - @State parentState: ClassA = new ClassA(1) - - build() { - Column() { - Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { - CompA({ aState: new ClassA(2), aLink: $parentState }) - } - Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { - CompA({ aLink: $parentState }) - } - Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { - CompA({ aState: new ClassA(3), aLink: $parentState }) - } - } - } -} - -@Component -struct CompA { - @State aState: any = false - @Link aLink: ClassA - - build() { - Column() { - CompB({ bLink: $aLink, bProp: this.aState }) - CompB({ bLink: $aState, bProp: false }) - } - } -} - -@Component -struct CompB { - @Link bLink: ClassA - @Prop bProp: boolean - - build() { - Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { - Text(JSON.stringify(this.bLink.a)).fontSize(30) - Text(JSON.stringify(this.bProp)).fontSize(30).fontColor(Color.Red) - }.margin(10) - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-custom-component-lifecycle-callbacks.md b/zh-cn/application-dev/ui/ts-custom-component-lifecycle-callbacks.md deleted file mode 100644 index 5a0126b00ae83f1e41792a2d60aa5032e5131525..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-custom-component-lifecycle-callbacks.md +++ /dev/null @@ -1,57 +0,0 @@ -# 自定义组件生命周期回调函数 - -自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 - - -## 生命周期回调函数定义 - -| 函数名 | 描述 | -| ---------------- | ------------------------------------------------------------ | -| aboutToAppear | 函数在创建自定义组件的新实例后,在执行其build函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build函数中生效。 | -| aboutToDisappear | 函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。 | -| onPageShow | 页面每次显示时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry修饰的自定义组件生效。 | -| onPageHide | 页面每次隐藏时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry修饰的自定义组件生效。 | -| onBackPress | 当用户点击返回按钮时触发,仅\@Entry修饰的自定义组件生效。
- 返回true表示页面自己处理返回逻辑, 不进行页面路由。
- 返回false表示使用默认的返回逻辑。
- 不返回值会作为false处理。 | -| onMeasure9+ | 框架会在自定义组件确定尺寸时,将该自定义组件的子节点信息和自身的尺寸范围通过onMeasure传递给该自定义组件。不允许在onMeasure函数中改变状态变量 | -| onLayout9+ | 框架会在自定义组件布局时,将该自定义组件的子节点信息和自身的尺寸范围通过onLayout传递给该自定义组件。不允许在onLayout函数中改变状态变量 | - - -## 示例 - -```ts -// xxx.ets -@Entry -@Component -struct CountDownTimerComponent { - @State countDownFrom: number = 10 - private timerId: number = -1 - - aboutToAppear(): void { - this.timerId = setInterval(() => { - if (this.countDownFrom <= 1) { - clearTimeout(this.timerId) - } - this.countDownFrom -= 1 - }, 1000) // decr counter by 1 every second - } - - aboutToDisappear(): void { - if (this.timerId > 0) { - clearTimeout(this.timerId) - this.timerId = -1 - } - } - - build() { - Text(`${this.countDownFrom} sec left`) - } -} -``` - -上述示例表明,生命周期函数对于允许CountDownTimerComponent管理其计时器资源至关重要,类似的函数也包括异步从网络请求加载资源。 - - -> **说明:** -> - 允许在生命周期函数中使用Promise和异步回调函数,比如网络资源获取,定时器设置等; -> -> - 不允许在生命周期函数中使用async await。 diff --git a/zh-cn/application-dev/ui/ts-framework-directory.md b/zh-cn/application-dev/ui/ts-framework-directory.md deleted file mode 100644 index 188fd56ebe989e67d3922cbfb099f2e6c78f00b8..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-framework-directory.md +++ /dev/null @@ -1,38 +0,0 @@ -# 目录结构 - - -FA应用的ArkTS模块(entry/src/main)的典型开发目录结构如下: - - -![zh-cn_image_0000001182200571](figures/zh-cn_image_0000001182200571.png) - - -**目录结构中文件分类如下:** - - -.ets结尾的ArkTS文件,用于描述UI布局、样式、事件交互和页面逻辑。 - -**各个文件夹和文件的作用:** - -- **app.ets**文件用于全局应用逻辑和应用生命周期管理。 - -- **pages**目录用于存放所有页面。 - -- **common**目录用于存放公共代码文件,比如:自定义组件和公共方法。 - - -> **说明:** -> -> - 资源目录resources文件夹位于src/main下,此目录下资源文件的详细规范以及子目录结构规范参看[资源文件的分类](../quick-start/resource-categories-and-access.md)。 -> - 页面支持导入TypeScript和JavaScript文件。 - -**js标签配置:** - - 开发框架需要在配置文件中标识相关的js标签,其中的每个元素代表一个JS模块的信息,包含了实例名称、页面路由、视图窗口等。 - - -> **说明:** -> -> FA模型请参考 [表22 js对象的内部结构说明](../quick-start/package-structure.md#module对象的内部结构)。 -> -> Stage模型请参考 [表3 module对象内部结构说明](../quick-start/stage-structure.md#module对象内部结构)。 diff --git a/zh-cn/application-dev/ui/ui-ts-components.md b/zh-cn/application-dev/ui/ui-ts-components.md deleted file mode 100644 index 775cb434d336028df04109f4a1eda38a1d007923..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ui-ts-components.md +++ /dev/null @@ -1,78 +0,0 @@ -# 初识Component - -在自定义组件之前,需要先了解什么是[组件和装饰器](#组件和装饰器),并进行初始化组件。然后通过[修改组件属性和构造参数](#修改组件属性和构造参数),实现一个自定义组件。 - - -## 组件和装饰器 - -在声明式UI中,所有的页面都是由组件构成。组件的数据结构为struct,装饰器@Component是组件化的标志。用@Component修饰的struct表示这个结构体有了组件化的能力。 - -自定义组件的声明方式为: - -```ts -@Component -struct MyComponent {} -``` - -在IDE创建工程模板中,MyComponent就是一个可以居中显示文字的自定义组件。开发者可以在Component的build方法里描述自己的UI结构,但需要遵循Builder的接口约束。 - -```ts -interface Builder { - build: () => void -} -``` - -@Entry修饰的Component表示该Component是页面的总入口,也可以理解为页面的根节点。值得注意的是,一个页面有且仅能有一个@Entry,只有被@Entry修饰的组件或者其子组件,才会在页面上显示。 - -@Component和@Entry都是基础且十分重要的装饰器。简单地理解,装饰器就是某一种修饰,给被装饰的对象赋予某一种能力,比如@Entry就是页面入口的能力,@Component就是组件化能力。 - -在了解了组件和装饰器这两个重要概念后,接下来可以开始开发健康饮食应用。 - - -## 修改组件属性和构造参数 - -开发者创建系统组件时,会显示其默认样式。开发者可以通过更改组件的属性样式来改变组件的视图显示。 - -1. 修改Text组件的fontSize属性来更改组件的字体大小,将字体大小设置为26,通过fontWeight属性更改字体粗细,将其设置为500。fontWeight属性支持三种设置方式: - 1. number类型的取值范围为100到900,取值间隔为100,默认为400,取值越大,字体越粗。 - 2. FontWeight为内置枚举类型,取值支持FontWeight.Lighter、FontWeight.Normal、FontWeight.Regular、FontWeight.Medium、FontWeight.Bold、FontWeight.Bolder。FontWeight.Normal即为400数值的字体粗细。 - 3. string类型仅支持number类型取值的字符串形式,例如"400",以及"bold"、"bolder"、"lighter"、"regular"、"medium",分别对应FontWeight中相应的枚举值。设置其他字符串则为无效,保持默认字体粗细显示。 - - 属性方法要紧随组件,通过“.”运算符连接,也可以通过链式调用的方式配置组件的多个属性。 - - ``` - @Entry - @Component - struct MyComponent { - build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('Hello World') - .fontSize(26) - .fontWeight(500) - } - .width('100%') - .height('100%') - } - } - ``` - - ![zh-cn_image_0000001168728272](figures/zh-cn_image_0000001168728272.png) - -2. 修改Text组件的显示内容“Hello World”为“Tomato”,通过修改Text组件的构造参数来实现。 - ``` - @Entry - @Component - struct MyComponent { - build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('Tomato') - .fontSize(26) - .fontWeight(500) - } - .width('100%') - .height('100%') - } - } - ``` - - ![zh-cn_image_0000001168888224](figures/zh-cn_image_0000001168888224.png) diff --git a/zh-cn/application-dev/ui/ui-ts-creating-project.md b/zh-cn/application-dev/ui/ui-ts-creating-project.md deleted file mode 100644 index e35ca9fa9b76d6dd69cbdc26864d649971265693..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ui-ts-creating-project.md +++ /dev/null @@ -1,65 +0,0 @@ -# 创建声明式UI工程 - - - -创建工程之前,首先需要安装DevEco Studio。 - - -1. 打开DevEco Studio,点击Create Project。如果已有一个工程,则点击File > New > New project。 - - ![zh-cn_image_0000001168956332](figures/zh-cn_image_0000001168956332.png) - -2. - 进入选择Ability Template界面,选择Empty Ability。 - - ![zh-cn_image_0000001168059158](figures/zh-cn_image_0000001168059158.png) - -3. 进入配置工程界面,将工程名字改为HealthyDiet,Project Type选择Application,Compile API选择8,UI Syntax选择eTS。DevEco Studio会默认将工程保存在C盘,如果要更改工程保存位置,点击Save Location的文件夹图标,自行指定工程创建位置。配置完成后点击Finish。 - - - ![zh-cn_image_0000001167746622](figures/zh-cn_image_0000001167746622.png) - -4. 工程创建完成后,打开app.ets。 - app.ets提供了应用生命周期的接口:onCreate和onDestroy,分别在应用创建之初和应用被销毁时调用。在app.ets里可以声明全局变量,并且声明的数据和方法是整个应用共享的。 - - ``` - export default { - onCreate() { - console.info('Application onCreate') - }, - onDestroy() { - console.info('Application onDestroy') - }, - } - ``` - -5. 在工程导航栏里,打开index.ets。该页面展示了当前的UI描述,声明式UI框架会自动生成一个组件化的struct,这个struct遵循Builder接口声明,在build方法里面声明当前的布局和组件。 - ``` - @Entry - @Component - struct MyComponent { - build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('Hello World') - .fontSize(50) - .fontWeight(FontWeight.Bold) - } - .width('100%') - .height('100%') - } - } - ``` - -6. 点击右侧的Previewer按钮,打开预览窗口。可以看到预览窗口中“Hello World”居中加粗显示。 - 如果没有Previewer按钮,点击settings > SDK Manager > OpenHarmony SDK> Tools 查看是否安装了Previewer。 - - ![zh-cn_image_0000001214595111](figures/zh-cn_image_0000001214595111.png) - -7. 应用安装到设备上运行应用。 - - 将设备连接电脑,等IDE识别到物理设备后,点击Run 'entry'按钮。 - ![zh-cn_image_0000001148858818](figures/zh-cn_image_0000001148858818.png) - - 在安装之前,需要配置应用签名。安装成功后,点击屏幕上的Run图标打开应用,可以看到居中加粗显示的“Hello World”。 - - ![zh-cn_image_0000001158896538](figures/zh-cn_image_0000001158896538.png) diff --git a/zh-cn/application-dev/ui/ui-ts-custom-component-lifecycle-callbacks.md b/zh-cn/application-dev/ui/ui-ts-custom-component-lifecycle-callbacks.md new file mode 100644 index 0000000000000000000000000000000000000000..be2c5d6bafd52e044f30edf0f9f6c392bbd0b8c8 --- /dev/null +++ b/zh-cn/application-dev/ui/ui-ts-custom-component-lifecycle-callbacks.md @@ -0,0 +1,135 @@ +# 自定义组件的生命周期 + +自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 + +> **说明:** +> +> - 允许在生命周期函数中使用Promise和异步回调函数,比如网络资源获取,定时器设置等; +> +> - 不允许在生命周期函数中使用async await。 + + +## aboutToAppear + +aboutToAppear?(): void + +aboutToAppear函数在创建自定义组件的新实例后,在执行其build函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build函数中生效。 + +## aboutToDisappear + +aboutToDisappear?(): void + +aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。 + +**示例1:** + +```ts +// xxx.ets +@Entry +@Component +struct CountDownTimerComponent { + @State countDownFrom: number = 10 + private timerId: number = -1 + + aboutToAppear(): void { + this.timerId = setInterval(() => { + if (this.countDownFrom <= 1) { + clearTimeout(this.timerId) // countDownFrom小于等于1时清除计时器 + } + this.countDownFrom -= 1 + }, 1000) // countDownFrom每1s减1 + } + + aboutToDisappear(): void { + if (this.timerId > 0) { + clearTimeout(this.timerId) + this.timerId = -1 + } + } + + build() { + Column() { + Text(`${this.countDownFrom} sec left`) + .fontSize(30) + .margin(30) + }.width('100%') + } +} +``` + +上述示例表明,生命周期函数对于允许CountDownTimerComponent管理其计时器资源至关重要,类似的函数也包括异步从网络请求加载资源。 + +## onPageShow + +onPageShow?(): void + +页面每次显示时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry修饰的自定义组件生效。 + +## onPageHide + +onPageHide?(): void + +页面每次隐藏时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry修饰的自定义组件生效。 + +## onBackPress + +onBackPress?(): void + +当用户点击返回按钮时触发,仅@Entry修饰的自定义组件生效。返回true表示页面自己处理返回逻辑,不进行页面路由,返回false表示使用默认的路由返回逻辑。不设置返回值按照false处理。 + +**示例2:** + +```ts +// xxx.ets +@Entry +@Component +struct IndexComponent { + @State textColor: Color = Color.Black + + onPageShow() { + this.textColor = Color.Blue + console.info('IndexComponent onPageShow') + } + + onPageHide() { + this.textColor = Color.Transparent + console.info('IndexComponent onPageHide') + } + + onBackPress() { + this.textColor = Color.Red + console.info('IndexComponent onBackPress') + } + + build() { + Column() { + Text('Hello World') + .fontColor(this.textColor) + .fontSize(30) + .margin(30) + }.width('100%') + } +} +``` + +## onLayout + +onLayout?(children: Array, constraint: [ConstraintSizeOptions](../reference/arkui-ts/ts-types.md#constraintsizeoptions)): void + +框架会在自定义组件布局时,将该自定义组件的子节点信息和自身的尺寸范围通过onLayout传递给该自定义组件。不允许在onLayout函数中改变状态变量。 + +## onMeasure + +onMeasure?(children: Array, constraint: [ConstraintSizeOptions](../reference/arkui-ts/ts-types.md#constraintsizeoptions)): void + +框架会在自定义组件确定尺寸时,将该自定义组件的子节点信息和自身的尺寸范围通过onMeasure传递给该自定义组件。不允许在onMeasure函数中改变状态变量。 + +## LayoutChild类型说明 + +| 参数 | 参数类型 | 描述 | +| ----- | ----------- | ----------- | +| name | string | 子组件名称 | +| id | string | 子组件id | +| constraint | [ConstraintSizeOptions](../reference/arkui-ts/ts-types.md#constraintsizeoptions) | 子组件约束尺寸 | +| borderInfo | { borderWidth: number, margin: [Margin](../reference/arkui-ts/ts-types.md#margin), padding: [Padding](../reference/arkui-ts/ts-types.md#padding) } | 子组件边框样式 | +| position | { x: number, y: number } | 子组件位置坐标 | diff --git a/zh-cn/application-dev/ui/ui-ts-developing-intro.md b/zh-cn/application-dev/ui/ui-ts-developing-intro.md new file mode 100644 index 0000000000000000000000000000000000000000..03f7fdf79c8b1f2d3480965fcbb0de3830bce65d --- /dev/null +++ b/zh-cn/application-dev/ui/ui-ts-developing-intro.md @@ -0,0 +1,223 @@ +# 声明式开发指导 + +## 开发说明 + +声明式UI的工程结构还请参考[OpenHarmony APP工程结构介绍](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-project-overview-0000001218440650#section133380945818)。其中,.ets结尾的ArkTS文件用于描述UI布局、样式、事件交互和页面逻辑,支持导入TypeScript和JavaScript文件。资源目录resources文件夹位于src/main下,此目录下资源文件的详细规范以及子目录结构规范参看[资源分类与访问](../quick-start/resource-categories-and-access.md)。 + +在开发页面之前,请先[学习ArkTS语言](../quick-start/arkts-get-started.md)了解声明式UI的基本语法。 + +在开发页面时,可先根据使用场景,在[常见布局](ui-ts-layout-linear.md)中选择合适的布局。再根据页面需要实现的内容,为页面添加系统内置组件,更新组件状态。页面开发过程中请参考[自定义组件的生命周期](ui-ts-custom-component-lifecycle-callbacks.md)了解如何添加需要的生命周期回调方法。 + +也可在页面中添加[绘图](../reference/arkui-ts/ts-drawing-components-circle.md)和[动画](../reference/arkui-ts/ts-animatorproperty.md),丰富页面的展现形态。还可以使用[路由](../reference/apis/js-apis-router.md)实现多个页面之间的跳转和数据传递。 + +另外请参考[性能提升的推荐方法](ui-ts-performance-improvement-recommendation.md),避免低性能代码对应用的性能造成负面影响。 + +## 创建页面 + +请先根据页面预期效果选择布局结构创建页面,并在页面中添加基础的系统内置组件。下述示例采用了[弹性布局(Flex)](ui-ts-layout-flex.md),对页面中的Text组件进行横纵向居中布局显示。 + + ```ts + // xxx.ets + @Entry + @Component + struct MyComponent { + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello') + } + .width('100%') + .height('100%') + } + } + ``` + +## 修改组件样式 + +创建系统内置组件时,若不设置属性方法,则会显示其默认样式。通过更改组件的属性样式设置可以改变组件的UI显示。 + +1. 通过修改Text组件的构造参数,将Text组件的显示内容修改为“Tomato”。 + +2. 修改Text组件的fontSize属性更改组件的字体大小,将字体大小设置为26,通过fontWeight属性更改字体粗细,将其设置为500。fontWeight属性支持三种设置方式: + + a. number类型的取值范围为100到900,取值间隔为100,默认为400,取值越大,字体越粗。 + + b. FontWeight为内置枚举类型,取值支持FontWeight.Lighter、FontWeight.Normal、FontWeight.Regular、FontWeight.Medium、FontWeight.Bold、FontWeight.Bolder。FontWeight.Normal即为400数值的字体粗细。 + + c. string类型仅支持number类型取值的字符串形式,例如"400",以及"bold"、"bolder"、"lighter"、"regular"、"medium",分别对应FontWeight中相应的枚举值。设置其他字符串则为无效,保持默认字体粗细显示。 + + 属性方法要紧随组件,通过“.”操作符连接,也可以通过链式调用的方式配置组件的多个属性。 + + ```ts + // xxx.ets + @Entry + @Component + struct MyComponent { + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Tomato') + .fontSize(26) + .fontWeight(500) + } + .width('100%') + .height('100%') + } + } + ``` + + ![zh-cn_image_0000001168888224](figures/zh-cn_image_0000001168888224.png) + +## 组件成员变量初始化 + +自定义组件的成员变量可以通过[本地初始化](../quick-start/arkts-restrictions-and-extensions.md#自定义组件成员变量初始化的方式与约束)和[在构造组件时通过构造参数初始化](../quick-start/arkts-restrictions-and-extensions.md#自定义组件成员变量初始化的方式与约束)两种方式实现,具体允许哪种方式取决于该变量所使用的装饰器: + + +**示例:** + +```ts +// xxx.ets +class ClassA { + public str: string + + constructor(str: string) { + this.str = str + } +} + +@Entry +@Component +struct Parent { + // Parent的变量parentState进行本地初始化 + @State parentState: ClassA = new ClassA('hello') + + build() { + Column() { + Row() { + CompA({ aState: new ClassA('Tomato'), aLink: $parentState }) + } + // aState在CompA中已进行初始化,因此可以缺省 + Row() { + CompA({ aLink: $parentState }) + } + }.width('100%') + } +} + +@Component +struct CompA { + // CompA中的变量aState进行本地初始化,aLink在Parent中使用时通过构造参数初始化 + @State aState: any = new ClassA('CompA') + @Link aLink: ClassA + + build() { + Row() { + Text(JSON.stringify(this.aState)).fontSize(20).margin(30) + Text(JSON.stringify(this.aLink)).fontSize(20).margin(30) + } + } +} +``` + +## 组件的状态更新 + +组件的状态可以通过动态修改组件成员变量的值来更新,下面以示例来进行说明。 + +**示例:** + +```ts +// xxx.ets +@Entry +@Component +struct ParentComp { + @State isCountDown: boolean = true + + build() { + Column() { + Text(this.isCountDown ? 'Count Down' : 'Stopwatch').fontSize(20).margin(20) + if (this.isCountDown) { + // 图片资源放在media目录下 + Image($r("app.media.countdown")).width(120).height(120) + TimerComponent({ counter: 10, changePerSec: -1, showInColor: Color.Red }) + } else { + // 图片资源放在media目录下 + Image($r("app.media.stopwatch")).width(120).height(120) + TimerComponent({ counter: 0, changePerSec: +1, showInColor: Color.Black }) + } + Button(this.isCountDown ? 'Switch to Stopwatch' : 'Switch to Count Down') + .onClick(() => { + this.isCountDown = !this.isCountDown + }) + }.width('100%') + } +} + +// 自定义计时器/倒计时组件 +@Component +struct TimerComponent { + @State counter: number = 0 + private changePerSec: number = -1 + private showInColor: Color = Color.Black + private timerId: number = -1 + + build() { + Text(`${this.counter}sec`) + .fontColor(this.showInColor) + .fontSize(20) + .margin(20) + } + + aboutToAppear() { + this.timerId = setInterval(() => { + this.counter += this.changePerSec + }, 1000) + } + + aboutToDisappear() { + if (this.timerId > 0) { + clearTimeout(this.timerId) + this.timerId = -1 + } + } +} +``` + +**初始创建和渲染:** + +1. 创建父组件ParentComp; + +2. 本地初始化ParentComp的状态变量isCountDown; + +3. 执行ParentComp的build函数; + +4. 创建Column组件; + 1. 创建Text组件,设置其文本展示内容,并将Text组件实例添加到Column中; + 2. 判断if条件,创建true条件下的元素; + 1. 创建Image组件,并设置其图片源地址; + 2. 使用给定的构造函数创建TimerComponent; + 1. 创建TimerComponent对象; + 2. 本地初始化成员变量初始值; + 3. 使用TimerComponent构造函数提供的参数更新成员变量的值; + 4. 执行TimerComponent的aboutToAppear函数; + 5. 执行TimerComponent的build函数,创建相应的UI描述结构; + 3. 创建Button内置组件,设置相应的内容。 + +**状态更新:** + +用户单击按钮时: + +1. ParentComp的isCountDown状态变量的值更改为false; + +2. 执行ParentComp的build函数; + +3. Column组件被重用并执行重新初始化; + +4. Column的子组件会重用内存中的对象,但会进行重新初始化; + 1. Text组件会被重用,但使用新的文本内容进行重新初始化; + 2. 判断if条件,使用false条件下的元素; + 1. 原来true条件的组件不再使用,将这些组件销毁; + 1. 销毁Image组件实例; + 2. 销毁TimerComponent组件实例,aboutToDisappear函数被调用; + 2. 创建false条件下的组件; + 1. 创建Image组件,并设置其图片源地址; + 2. 使用给定的构造函数重新创建TimerComponent; + 3. 初始化TimerComponent,并调用aboutToAppear函数和build函数。 + 3. 重用Button组件,使用新的图片源地址。 diff --git a/zh-cn/application-dev/ui/ui-ts-overview.md b/zh-cn/application-dev/ui/ui-ts-overview.md index 348ce1cde17b33f3a6bb7fe393e74427f6852a63..7c6d9bf7771d91be396b6f5b94ad6eb881024a1a 100644 --- a/zh-cn/application-dev/ui/ui-ts-overview.md +++ b/zh-cn/application-dev/ui/ui-ts-overview.md @@ -1,30 +1,25 @@ # 概述 -基于ArkTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。 +基于ArkTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、支持跨设备的UI开发框架,支持开发者高效地构建OpenHarmony应用UI界面。 ## 基础能力 -使用基于ArkTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。 - -请参考[基于ArkTS的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解组件,更好地开发应用。 - +使用基于ArkTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动画和状态管理三个维度来提供UI能力,还提供了系统能力接口以实现系统能力的极简调用。 +ArkTS语言的基础知识请参考[学习ArkTS语言](../quick-start/arkts-get-started.md)文档;此外,请参考[基于ArkTS的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解内置组件,更好地开发应用。 - **开箱即用的组件** - 框架提供丰富的系统预置组件,可以通过链式调用的方式设置系统组件的渲染效果。开发者可以组合系统组件为自定义组件,通过这种方式将页面组件化为一个个独立的UI单元,实现页面不同单元的独立创建、开发和复用,使页面具有更强的工程性。 - + 框架提供丰富的系统内置组件,可以通过链式调用的方式设置系统组件的渲染效果。开发者可以组合系统组件为自定义组件,通过这种方式将页面组件化为一个个独立的UI单元,实现页面不同单元的独立创建、开发和复用,使页面具有更强的工程性。 - **丰富的动效接口** 提供svg标准的绘制图形能力,同时开放了丰富的动效接口,开发者可以通过封装的物理模型或者调用动画能力接口来实现自定义动画轨迹。 - - **状态与数据管理** 状态数据管理作为基于ArkTS的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。 - - **系统能力接口** 使用基于ArkTS的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。 @@ -32,8 +27,6 @@ ## 整体架构 - - ![zh-cn_image_0000001169532276](figures/zh-cn_image_0000001169532276.png) - **声明式UI前端** @@ -50,7 +43,7 @@ - **渲染引擎** - 提供了高效的绘制能力,将渲染管线收集的渲染指令,绘制到屏幕能力。 + 提供了高效的绘制能力,将渲染管线收集的渲染指令,绘制到屏幕的能力。 - **平台适配层** diff --git a/zh-cn/application-dev/ui/ts-performance-improvement-recommendation.md b/zh-cn/application-dev/ui/ui-ts-performance-improvement-recommendation.md similarity index 100% rename from zh-cn/application-dev/ui/ts-performance-improvement-recommendation.md rename to zh-cn/application-dev/ui/ui-ts-performance-improvement-recommendation.md