diff --git a/zh-cn/application-dev/quick-start/Readme-CN.md b/zh-cn/application-dev/quick-start/Readme-CN.md index a511a286daafa2b586cf707b8cbb943d1f9013ec..316a8b27a9dd090b41a1e6999f46ce559403ebd1 100755 --- a/zh-cn/application-dev/quick-start/Readme-CN.md +++ b/zh-cn/application-dev/quick-start/Readme-CN.md @@ -9,4 +9,15 @@ - [应用包结构说明(FA模型)](package-structure.md) - [应用包结构说明(Stage模型)](stage-structure.md) - [SysCap说明](syscap.md) - - [HarmonyAppProvision配置文件](app-provision-structure.md) \ No newline at end of file + - [HarmonyAppProvision配置文件](app-provision-structure.md) + - 学习ArkTS语言 + - [初识ArkTS语言](arkts-get-started.md) + - eTS语法(声明式UI) + - [基本UI描述](arkts-basic-ui-description.md) + - 状态管理 + - [基本概念](arkts-state-mgmt-concepts.md) + - [页面级变量的状态管理](arkts-state-mgmt-page-level.md) + - [应用级变量的状态管理](arkts-state-mgmt-application-level.md) + - [动态构建UI元素](arkts-dynamic-ui-elememt-building.md) + - [渲染控制](arkts-rendering-control.md) + - [使用限制与扩展](arkts-restrictions-and-extensions.md) \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/arkts-basic-ui-description.md b/zh-cn/application-dev/quick-start/arkts-basic-ui-description.md new file mode 100644 index 0000000000000000000000000000000000000000..9bcdcd80c6716abf591cd38c90e15163c17e4fcc --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-basic-ui-description.md @@ -0,0 +1,195 @@ +# 基本UI描述 + +ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结构,构成一个自定义组件。自定义组件中提供了一个build函数,开发者需在该函数内以链式调用的方式进行基本的UI描述,UI描述的方法请参考[UI描述规范](#ui描述规范)。 + +## 基本概念 + +- struct:组件可以基于struct实现,不能有继承关系,对于struct的实例化,可以省略new。 + +- 装饰器:装饰器给被装饰的对象赋予某一种能力,其不仅可以装饰类或结构体,还可以装饰类的属性。多个装饰器可以叠加到目标元素,定义在同一行上或者多行上,推荐定义在多行上。 + + ```ts + @Entry + @Component + struct MyComponent { + } + ``` + +- build函数:自定义组件必须定义build函数,并且自定义组件禁止自定义构造函数。build函数满足Builder构造器接口定义,用于定义组件的声明式UI描述。 + + ```ts + interface Builder { + build: () => void + } + ``` + +- @Component:装饰struct,结构体在装饰后具有基于组件的能力,需要实现build方法来更新UI。 + +- @Entry: 装饰struct,组件被装饰后作为页面的入口,页面加载时将被渲染显示。 + +- @Preview:装饰struct, 用@Preview装饰的自定义组件可以在DevEco Studio的预览器上进行实时预览,加载页面时,将创建并呈现@Preview装饰的自定义组件。 + + > **说明:** 在单个源文件中,最多可以使用10个@Preview装饰自定义组件,更多说明请参考[查看ArkTS组件预览效果](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-previewing-app-service-0000001218760596#section146052489820)。 + +- 链式调用:以 "." 链式调用的方式配置UI结构及其属性、事件等。 + +## UI描述规范 + +### 无参数构造配置 + +组件的接口定义不包含必选构造参数,组件后面的“()”中不需要配置任何内容。例如,Divider组件不包含构造参数: + +```ts +Column() { + Text('item 1') + Divider() + Text('item 2') +} +``` + +### 必选参数构造配置 + +如果组件的接口定义中包含必选构造参数,则在组件后面的“()”中必须配置参数,参数可以使用常量进行赋值。 + +例如: + +- Image组件的必选参数src: + + ```ts + Image('http://xyz/a.jpg') + ``` + +- Text组件的必选参数content: + + ```ts + Text('123') + ``` + +变量或表达式也可以用于参数赋值,其中表达式返回的结果类型必须满足参数类型要求。例如,传递变量或表达式来构造Image和Text组件的参数: + +```ts +Image(this.imagePath) +Image('http://' + this.imageUrl) +Text(`count: ${this.count}`) +``` + +### 属性配置 + +使用属性方法配置组件的属性,属性方法紧随组件,并用"."运算符连接。 + +- 配置Text组件的字体大小属性: + + ```ts + Text('123') + .fontSize(12) + ``` + +- 使用"."操作进行链式调用并同时配置组件的多个属性,如下所示: + + ```ts + Image('a.jpg') + .alt('error.jpg') + .width(100) + .height(100) + ``` + +- 除了直接传递常量参数外,还可以传递变量或表达式,如下所示: + + ```ts + Text('hello') + .fontSize(this.size) + Image('a.jpg') + .width(this.count % 2 === 0 ? 100 : 200) + .height(this.offset + 100) + ``` + +- 对于系统内置组件,框架还为其属性预定义了一些[枚举类型](../reference/arkui-ts/ts-appendix-enums.md)供开发人员调用,枚举类型必须满足参数类型要求,枚举值可以作为参数传递。可以按以下方式配置Text组件的颜色和字体属性: + + ```ts + Text('hello') + .fontSize(20) + .fontColor(Color.Red) + .fontWeight(FontWeight.Bold) + ``` + +### 事件配置 + +通过事件方法可以配置组件支持的事件。 + +- 使用lambda表达式配置组件的事件方法: + + ```ts + Button('add counter') + .onClick(() => { + this.counter += 2 + }) + ``` + +- 使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数体中的this引用包含的组件: + + ```ts + Button('add counter') + .onClick(function () { + this.counter += 2 + }.bind(this)) + ``` + +- 使用组件的成员函数配置组件的事件方法: + + ```ts + myClickHandler(): void { + + } + + ... + + Button('add counter') + .onClick(this.myClickHandler) + ``` + +### 子组件配置 + +对于支持子组件配置的组件,例如容器组件,在"{ ... }"里为组件添加子组件的UI描述。Column、Row、Stack、Button、Grid和List组件都是容器组件。 + +- 以下是简单的Column示例: + + ```ts + Column() { + Text('Hello') + .fontSize(100) + Divider() + Text(this.myText) + .fontSize(100) + .fontColor(Color.Red) + } + ``` + +- 可以嵌套多个子组件: + + ```ts + Column() { + Column() { + Button() { + Text('+ 1') + }.type(ButtonType.Capsule) + .onClick(() => console.log ('+1 clicked!')) + Image('1.jpg') + } + Divider() + Column() { + Button() { + Text('+ 2') + }.type(ButtonType.Capsule) + .onClick(() => console.log ('+2 clicked!')) + Image('2.jpg') + } + Divider() + Column() { + Button() { + Text('+ 3') + }.type(ButtonType.Capsule) + .onClick(() => console.log('+3 clicked!')) + Image('3.jpg') + } + }.alignItems(HorizontalAlign.Center) + ``` \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ts-component-based-builder.md b/zh-cn/application-dev/quick-start/arkts-dynamic-ui-elememt-building.md similarity index 54% rename from zh-cn/application-dev/ui/ts-component-based-builder.md rename to zh-cn/application-dev/quick-start/arkts-dynamic-ui-elememt-building.md index 7f21c9e5e18d080b28bd9ac6d4d0b65c57daa633..83f0be992b6547d997e2723b4fb29f44a65141c3 100644 --- a/zh-cn/application-dev/ui/ts-component-based-builder.md +++ b/zh-cn/application-dev/quick-start/arkts-dynamic-ui-elememt-building.md @@ -1,7 +1,11 @@ -# @Builder +# 动态构建UI元素 +前面章节介绍的是如何创建一个组件内部UI结构固定的自定义组件,为了满足开发者自定义组件内部UI结构的需求,ArkTS同时提供了动态构建UI元素的能力。 -@Builder装饰的方法用于定义组件的声明式UI描述,在一个自定义组件内快速生成多个布局内容。如果\@Builder装饰的方法中使用了自定义组件,那么该方法每次被调用时,对应的自定义组件均会重新创建。\@Builder装饰方法的功能和语法规范与[build函数](ts-function-build.md)相同。 +## @Builder + + +可通过@Builder装饰器进行描述,该装饰器可以修饰一个函数,此函数可以在build函数之外声明,并在build函数中或其他@Builder修饰的函数中使用,在一个自定义组件内快速生成多个布局内容。使用方式如下面示例所示。 ```ts @@ -80,6 +84,7 @@ struct CompA { } ``` ## @BuilderParam8+ + @BuilderParam装饰器用于修饰自定义组件内函数类型的属性(例如:`@BuilderParam content: () => any;`),并且在初始化自定义组件时被@BuilderParam修饰的属性必须赋值。 ### 引入动机 @@ -87,6 +92,7 @@ struct CompA { 当开发者创建自定义组件,想对该组件添加特定功能时(如:仅对自定义组件添加一个点击跳转操作)。若直接在组件内嵌入事件方法,将会导致所有初始化该组件的地方均增加了该功能。为解决此问题,引入了@BuilderParam装饰器,此装饰器修饰的属性值可为@Builder修饰的方法,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的的功能。 ### 参数初始化组件 + 通过参数初始化组件时,将@Builder装饰的方法赋值给@BuilderParam修饰的属性,并在自定义组件内调用content属性值。对@BuilderParam修饰的属性进行赋值时不带参数(如:`content: this.specificParam`),则此属性的类型需定义成无返回值的函数(如:`@BuilderParam content: () => void`)。若带参数(如:`callContent: this.specificParam1("111")`),则此属性的类型需定义成any(如:`@BuilderParam callContent: any;`)。 ```ts @@ -135,10 +141,13 @@ struct CustomContainerUser { } } ``` + ### 尾随闭包初始化组件 -在自定义组件中使用@BuilderParam修饰的属性接收尾随闭包(在初始化自定义组件时,组件名称紧跟一个大括号“{}”形成尾随闭包场景(`CustomComponent(){}`)。开发者可把尾随闭包看做一个容器,向其填充内容,如在闭包内增加组件(`{Column(){Text("content")}`),闭包内语法规范与[build](../ui/ts-function-build.md)一致。此场景下自定义组件内有且仅有一个使用@BuilderParam修饰的属性。 + +在自定义组件中使用@BuilderParam修饰的属性接收尾随闭包(在初始化自定义组件时,组件名称紧跟一个大括号“{}”形成尾随闭包场景(`CustomComponent(){}`)。开发者可把尾随闭包看做一个容器,向其填充内容,如在闭包内增加组件(`{Column(){Text("content")}`),闭包内语法规范与build函数一致。此场景下自定义组件内有且仅有一个使用@BuilderParam修饰的属性。 示例:在闭包内增加Column组件并添加点击事件,在新增的Column组件内调用@Builder修饰的specificParam方法,点击Column组件后该改变自定义组件中header的属性值为“changeHeader”。并且在初始化自定义组件时会把尾随闭包的内容赋值给使用@BuilderParam修饰的closer属性。 + ```ts // xxx.ets @Component @@ -180,3 +189,156 @@ struct CustomContainerUser { } } ``` + +## @Styles + +ArkTS为了避免开发者对重复样式的设置,通过@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置使用。@Styles装饰器将新的属性函数添加到基本组件上,如Text、Column、Button等。当前@Styles仅支持通用属性。通过@Styles装饰器可以快速定义并复用组件的自定义样式。 + +@Styles可以定义在组件内或组件外,在组件外定义时需在方法前添加function关键字,组件内定义时不需要添加function关键字。 + +```ts +// xxx.ets +@Styles function globalFancy() { + .backgroundColor(Color.Red) +} + +@Entry +@Component +struct FancyUse { + @Styles componentFancy() { + .backgroundColor(Color.Blue) + } + build() { + Column({ space: 10 }) { + Text("Fancy") + .globalFancy() + .width(100) + .height(100) + .fontSize(30) + Text("Fancy") + .componentFancy() + .width(100) + .height(100) + .fontSize(30) + } + } +} +``` + +@Styles还可以在[StateStyles](../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md)属性内部使用,在组件处于不同的状态时赋予相应的属性。 + +在StateStyles内可以直接调用组件外定义的Styles,但需要通过this关键字调用组件内定义的Styles。 + +```ts +// xxx.ets +@Styles function globalFancy() { + .width(100) + .height(100) +} + +@Entry +@Component +struct FancyUse { + @Styles componentFancy() { + .width(50) + .height(50) + } + build() { + Row({ space: 10 }) { + Button() { + Text("Fancy") + } + .stateStyles({ + normal: { + .width(80) + .height(80) + }, + disabled: this.componentFancy, + pressed: globalFancy + }) + } + } +} +``` + +## @Extend + +@Extend装饰器将新的属性函数添加到内置组件上,如Text、Column、Button等。通过@Extend装饰器可以快速的扩展原生组件。@Extend装饰器不能用在自定义组件struct定义框内。 + +```ts +// xxx.ets +@Extend(Text) function fancy(fontSize: number) { + .fontColor(Color.Red) + .fontSize(fontSize) + .fontStyle(FontStyle.Italic) +} + +@Entry +@Component +struct FancyUse { + build() { + Row({ space: 10 }) { + Text("Fancy") + .fancy(16) + Text("Fancy") + .fancy(24) + } + } +} +``` + +> **说明:** +> +> - @Extend装饰器不能用在自定义组件struct定义框内。 +> - @Extend装饰器内仅支持属性函数语句。 + +## @CustomDialog + +@CustomDialog装饰器用于装饰自定义弹窗,使得弹窗可以动态设置样式。 + +```ts +// custom-dialog-demo.ets +@CustomDialog +struct DialogExample { + controller: CustomDialogController; + action: () => void; + + build() { + Row() { + Button ("Close CustomDialog") + .onClick(() => { + this.controller.close(); + this.action(); + }) + }.padding(20) + } +} + +@Entry +@Component +struct CustomDialogUser { + dialogController : CustomDialogController = new CustomDialogController({ + builder: DialogExample({action: this.onAccept}), + cancel: this.existApp, + autoCancel: true + }); + + onAccept() { + console.log("onAccept"); + } + existApp() { + console.log("Cancel dialog!"); + } + + build() { + Column() { + Button("Click to open Dialog") + .onClick(() => { + this.dialogController.open() + }) + } + } +} +``` + +![custom-dialog-demo](figures/custom-dialog-demo.gif) \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/arkts-get-started.md b/zh-cn/application-dev/quick-start/arkts-get-started.md new file mode 100644 index 0000000000000000000000000000000000000000..f8743bef0d4ec84731ff95c6f0d299a3c43c5077 --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-get-started.md @@ -0,0 +1,30 @@ +# 初识ArkTS语言 + +ArkTS是OpenHarmony优选的主力应用开发语言。ArkTS基于TypeScript(简称TS)语言扩展而来,是TS的超集。 + +- ArkTS继承了TS的所有特性。 + +- 当前,ArkTS在TS基础上主要扩展了[声明式UI](arkts-basic-ui-description.md)能力,让开发者以更简洁、更自然的方式开发高性能应用。 + + 当前扩展的声明式UI包括如下特性。 + + - [基本UI描述](ets-basic-ui-description.md):ArkTS定义了各种装饰器、自定义组件、UI描述机制,再配合UI开发框架中的UI内置组件、事件方法、属性方法等共同构成了UI开发的主体。 + - [状态管理](arkts-state-mgmt-page-level.md):ArkTS提供了多维度的状态管理机制,在UI开发框架中,和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,也可以是全局范围内的传递,还可以是 跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的利用这些能力来实现数据和UI的联动。 + - [动态构建UI元素](arkts-dynamic-ui-elememt-building.md):ArkTS提供了动态构建UI元素的能力,不仅可以自定义组件内部的UI结构,还可复用组件样式,扩展原生组件。 + - [渲染控制](arkts-rendering-control.md):ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的部分内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。 + - [使用限制与扩展](arkts-restrictions-and-extensions.md):ArkTS在使用过程中存在限制与约束,同时也扩展了双向绑定等能力。 + +- 未来,ArkTS会结合应用开发/运行的需求持续演进,逐步提供并行和并发能力增强、类型系统增强、分布式开发范式等更多特性。 + +下面我们以一个具体的示例来说明ArkTS的基本组成。如下图所示的代码示例,UI界面会两段文本和一个按钮,当开发者点击按钮时,文本内容会从'Hello World'变为 'Hello ArkUI'。 + +![arkts-get-started](figures/arkts-get-started.png) + +这个示例中所包含的ArkTS声明式开发范式的基本组成说明如下: + +- 装饰器: 用于装饰类、结构、方法以及变量,赋予其特殊的含义,如上述示例中@Entry、@Component和@State都是装饰器。 具体而言,@Component表示这是个自定义组件;@Entry则表示这是个入口组件;@State表示组件中的状态变量,这个状态变换会引起UI变更。 +- 自定义组件:可复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Hello。 +- UI描述:声明式的方法来描述UI的结构,例如build()方法中的代码块。 +- 内置组件:ArkTS中默认内置的基本组件和布局组件,开发者可以直接调用,如Column、Text、Divider、Button等。 +- 属性方法:用于组件属性的配置,如fontSize()、width()、height()、color()等,可通过链式调用的方式设置多项属性。 +- 事件方法:用于添加组件对事件的响应逻辑,统一通过事件方法进行设置,如跟随在Button后面的onClick()。 diff --git a/zh-cn/application-dev/quick-start/arkts-rendering-control.md b/zh-cn/application-dev/quick-start/arkts-rendering-control.md new file mode 100644 index 0000000000000000000000000000000000000000..71210480f08d4059409107f24d786d51e4da663f --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-rendering-control.md @@ -0,0 +1,270 @@ +# 渲染控制 + +ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的部分内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。 + +## 条件渲染 + +使用if/else进行条件渲染。 + + +> **说明:** +> +> - if条件语句可以使用状态变量。 +> +> - 使用if可以使子组件的渲染依赖条件语句。 +> +> - 必须在容器组件内使用。 +> +> - 某些容器组件限制子组件的类型或数量。将if放置在这些组件内时,这些限制将应用于if和else语句内创建的组件。例如,Grid组件的子组件仅支持GridItem组件,在Grid组件内使用if时,则if条件语句内仅允许使用GridItem组件。 + + +```ts +Column() { + if (this.count < 0) { + Text('count is negative') + } else if (this.count % 2 === 0) { + Divider() + Text('even') + } else { + Divider() + Text('odd') + } +} +``` + +## 循环渲染 + +通过循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件,可减少代码复杂度。 + +``` + ForEach( + arr: any[], + itemGenerator: (item: any, index?: number) => void, + keyGenerator?: (item: any, index?: number) => string + ) +``` + +**参数:** + +| 参数名 | 参数类型 | 必填 | 参数描述 | +| ------------- | ------------------------------------- | ---- | ------------------------------------------------------------ | +| arr | any[] | 是 | 必须是数组,允许空数组,空数组场景下不会创建子组件。同时允许设置返回值为数组类型的函数,例如arr.slice(1, 3),设置的函数不得改变包括数组本身在内的任何状态变量,如Array.splice、Array.sort或Array.reverse这些改变原数组的函数。 | +| itemGenerator | (item: any, index?: number) => void | 是 | 生成子组件的lambda函数,为给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{....}”中。 | +| keyGenerator | (item: any, index?: number) => string | 否 | 匿名参数,用于给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则ForEach中的所有节点都将重建。 | + +> **说明:** +> +> - ForEach组件必须在容器组件内使用; +> +> - 生成的子组件允许在ForEach的父容器组件中,允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中; +> +> - 子项生成器函数的调用顺序不一定和数组中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作: +> +> ``` +> ForEach(anArray.map((item1, index1) => { return { i: index1 + 1, data: item1 }; }), +> item => Text(`${item.i}. item.data.label`), +> item => item.data.id.toString()) +> ``` + +## 示例 + +```ts +// xxx.ets +@Entry +@Component +struct MyComponent { + @State arr: number[] = [10, 20, 30] + + build() { + Column() { + Button() { + Text('Reverse Array') + }.onClick(() => { + this.arr.reverse() + }) + + ForEach(this.arr, + (item: number) => { + Text(`item value: ${item}`) + Divider() + }, + (item: number) => item.toString() + ) + } + } +} +``` + +## 数据懒加载 + +通过数据懒加载(LazyForEach组件)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。 + +```ts +LazyForEach( + dataSource: IDataSource, + itemGenerator: (item: any) => void, + keyGenerator?: (item: any) => string +): void + +interface IDataSource { + totalCount(): number; + getData(index: number): any; + registerDataChangeListener(listener: DataChangeListener): void; + unregisterDataChangeListener(listener: DataChangeListener): void; +} + +interface DataChangeListener { + onDataReloaded(): void; + onDataAdd(index: number): void; + onDataMove(from: number, to: number): void; + onDataDelete(index: number): void; + onDataChange(index: number): void; +} +``` + +**参数:** + +| 参数名 | 参数类型 | 必填 | 参数描述 | +| ------------- | --------------------- | ---- | ------------------------------------------------------------ | +| dataSource | IDataSource | 是 | 实现IDataSource接口的对象,需要开发者实现相关接口。 | +| itemGenerator | (item: any) => void | 是 | 生成子组件的lambda函数,为给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{....}”中。 | +| keyGenerator | (item: any) => string | 否 | 匿名函数,用于键值生成,为给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 | + +表2 IDataSource类型说明 + +| 名称 | 描述 | +| ------------------------------------------------------------ | ---------------------- | +| totalCount(): number | 获取数据总数。 | +| getData(index: number): any | 获取索引对应的数据。 | +| registerDataChangeListener(listener:DataChangeListener): void | 注册改变数据的控制器。 | +| unregisterDataChangeListener(listener:DataChangeListener): void | 注销改变数据的控制器。 | + +表3 DataChangeListener类型说明 + +| 名称 | 描述 | +| -------------------------------------------------------- | -------------------------------------- | +| onDataReloaded(): void | 重新加载所有数据。 | +| onDataAdded(index: number): void (deprecated) | 通知组件index的位置有数据添加。 | +| onDataMoved(from: number, to: number): void (deprecated) | 通知组件数据从from的位置移到to的位置。 | +| onDataDeleted(index: number): void (deprecated) | 通知组件index的位置有数据删除。 | +| onDataChanged(index: number): void (deprecated) | 通知组件index的位置有数据变化。 | +| onDataAdd(index: number): void 8+ | 通知组件index的位置有数据添加。 | +| onDataMove(from: number, to: number): void 8+ | 通知组件数据从from的位置移到to的位置。 | +| onDataDelete(index: number): void 8+ | 通知组件index的位置有数据删除。 | +| onDataChange(index: number): void 8+ | 通知组件index的位置有数据变化。 | + +## 示例 + +```ts +class BasicDataSource implements IDataSource { + private listeners: DataChangeListener[] = [] + + public totalCount(): number { + return 0 + } + public getData(index: number): any { + return undefined + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener') + this.listeners.push(listener) + } + } + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener') + this.listeners.splice(pos, 1) + } + } + + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded() + }) + } + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index) + }) + } + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index) + }) + } + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index) + }) + } + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to) + }) + } +} + +class MyDataSource extends BasicDataSource { + private dataArray: string[] = ['/path/image0', '/path/image1', '/path/image2', '/path/image3'] + + public totalCount(): number { + return this.dataArray.length + } + public getData(index: number): any { + return this.dataArray[index] + } + + public addData(index: number, data: string): void { + this.dataArray.splice(index, 0, data) + this.notifyDataAdd(index) + } + public pushData(data: string): void { + this.dataArray.push(data) + this.notifyDataAdd(this.dataArray.length - 1) + } +} + +@Entry +@Component +struct MyComponent { + private data: MyDataSource = new MyDataSource() + build() { + List({space: 3}) { + LazyForEach(this.data, (item: string) => { + ListItem() { + Row() { + Image(item).width("30%").height(50) + Text(item).fontSize(20).margin({left:10}) + }.margin({left: 10, right: 10}) + } + .onClick(()=>{ + this.data.pushData('/path/image' + this.data.totalCount()) + }) + }, item => item) + } + } +} +``` + +> **说明:** +> +> - 数据懒加载必须在容器组件内使用,且仅有List、Grid以及Swiper组件支持数据的懒加载(即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次加载所有的数据; +> +> - LazyForEach在每次迭代中,必须且只允许创建一个子组件; +> +> - 生成的子组件必须允许在LazyForEach的父容器组件中; +> +> - 允许LazyForEach包含在if/else条件渲染语句中,不允许LazyForEach中出现if/else条件渲染语句; +> +> - 为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,仅itemGenerator中的UI描述的组件内使用了状态变量时,才会触发组件刷新; +> +> - 子项生成器函数的调用顺序不一定和数据源中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作: +> +> ```ts +> LazyForEach(dataSource, +> item => Text(`${item.i}. item.data.label`)), +> item => item.data.id.toString()) +> ``` \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..0d7caec54ab82007b88df7d4c6684a19d9670c4f --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md @@ -0,0 +1,72 @@ +# 使用限制与扩展 + +## 在生成器函数中的使用限制 + +ArkTS语言的使用在生成器函数中存在一定的限制: + +- 表达式仅允许在字符串(${expression})、if条件、ForEach的参数和组件的参数中使用; +- 任何表达式都不能导致任何应用程序状态变量(@State、@Link、@Prop)的改变,否则会导致未定义和潜在不稳定的框架行为; +- 生成器函数内部不能有局部变量。 + +上述限制都不适用于事件处理函数(例如onClick)的匿函数实现。 + +## 变量的双向绑定 + +ArkTS支持通过$$双向绑定变量,通常应用于状态值频繁改变的变量。 + +- 当前$$支持基础类型变量,以及@State、@Link和@Prop装饰的变量。 +- 当前$$仅支持[bindPopup](../reference/arkui-ts/ts-universal-attributes-popup.md)属性的show参数和@State变量之间的渲染,Radio组件的checked属性。 +- $$绑定的变量变更时,仅渲染当前组件,提高渲染速度。 + +```ts +// xxx.ets +@Entry +@Component +struct bindPopup { + @State customPopup: boolean = false + build() { + column() { + button() { + Text('Popup') + } + .onClick(() => { + this.customPopup = !this.customPopup + }) + .bindPopup( + $$this.customPopup, { + mesage: "showPopup" + } + ) + } + } +} + +``` + +## 状态变量多种数据类型声明使用限制 + +@State、@Provide、 @Link和@Consume四种状态变量的多种数据类型只能同时由简单数据类型或引用数据类型其中一种构成。 + +示例: + +```ts +// xxx.ets +@Entry +@Component +struct Index { + //错误写法: @State message: string | Resource = 'Hello World' + @State message: string = 'Hello World' + + build() { + Row() { + Column() { + Text(`${ this.message }`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} +``` \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/arkts-state-mgmt-application-level.md b/zh-cn/application-dev/quick-start/arkts-state-mgmt-application-level.md new file mode 100644 index 0000000000000000000000000000000000000000..042cf54d6fb8a055cddebca958d51c9cfcf96fee --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-state-mgmt-application-level.md @@ -0,0 +1,236 @@ +# 应用级变量的状态管理 + +在前面的章节中,已经讲述了如何管理页面级变量的状态,本章将说明如何管理应用级变量的状态。 + +## AppStorage + +AppStorage是应用程序中的单例对象,由UI框架在应用程序启动时创建,在应用程序退出时销毁,为应用程序范围内的可变状态属性提供中央存储。 + +AppStorage包含整个应用程序中需要访问的所有状态属性,只要应用程序保持运行,AppStorage就会保存所有属性及属性值,属性值可以通过唯一的键值进行访问。 + + +组件可以通过装饰器将应用程序状态数据与AppStorage进行同步,应用业务逻辑的实现也可以通过接口访问AppStorage。 + + +AppStorage的选择状态属性可以与不同的数据源或数据接收器同步,这些数据源和接收器可以是设备上的本地或远程,并具有不同的功能,如数据持久性。这样的数据源和接收器可以独立于UI在业务逻辑中实现。 + +默认情况下,AppStorage中的属性是可变的,AppStorage还可使用不可变(只读)属性。 + + AppStorage的具体接口请参考[状态管理]() + +### @StorageLink装饰器 + +组件通过使用@StorageLink(key)装饰的状态变量,与AppStorage建立双向数据绑定,key为AppStorage中的属性键值。当创建包含@StorageLink的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。在UI组件中对@StorageLink的状态变量所做的更改将同步到AppStorage,并从AppStorage同步到任何其他绑定实例中,如PersistentStorage或其他绑定的UI组件。 + +### @StorageProp装饰器 + +组件通过使用@StorageProp(key)装饰的状态变量,将与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StoageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中的属性值的更改会导致绑定的UI组件进行状态更新。 + +## 示例 + +每次用户单击Count按钮时,this.varA变量值都会增加,此变量与AppStorage中的varA同步。每次用户单击当前语言按钮时,修改AppStorage中的languageCode,此修改会同步给this.lang变量。 + +```ts +// xxx.ets + +@Entry +@Component +struct ComponentA { + @StorageLink('varA') varA: number = 2 + @StorageProp('languageCode') lang: string = 'en' + private label: string = 'count' + + aboutToAppear() { + this.label = (this.lang === 'zh') ? '数' : 'Count' + } + + build() { + Column(){ + Row({ space: 20 }) { + Button(`${this.label}: ${this.varA}`) + .onClick(() => { + AppStorage.Set('varA', AppStorage.Get('varA') + 1) + }) + Button(`lang: ${this.lang}`) + .onClick(() => { + if (this.lang === 'zh') { + AppStorage.Set('languageCode', 'en') + } else { + AppStorage.Set('languageCode', 'zh') + } + this.label = (this.lang === 'zh') ? '数' : 'Count' + }) + } + .margin({ bottom: 50 }) + Row(){ + Button(`更改@StorageLink修饰的变量:${this.varA}`).fontSize(10) + .onClick(() => { + this.varA++ + }) + }.margin({ bottom: 50 }) + Row(){ + Button(`更改@StorageProp修饰的变量:${this.lang}`).fontSize(10) + .onClick(() => { + this.lang = 'test' + }) + } + } + } +} +``` + + ![appstorage](figures/appstorage.gif) + +## LocalStorage + +> **说明:** 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 + +LocalStorage是应用程序中的存储单元,生命周期跟随其关联的Ability。LocalStorage为应用程序范围内的可变状态属性和非可变状态属性提供存储,可变状态属性和非可变状态属性是构建应用程序UI的一部分,如一个Ability的UI。 + +应用层:一个应用程序可以创建多个LocalStorage实例,应用程序的每一个Ability对应一个LocalStorage实例。 + +Ability: 一个应用程序可以拥有多个Ability,一个Ability中的所有子组件最多可以分配一个LocalStorage实例。并且,Ability中的所有子组件都将继承对此LocalStorage实例存储对象的访问权。 + +一个组件最多可以访问一个LocalStorage实例,一个LocalStorage对象可以分配给多个组件。 + +## @LocalStorageLink装饰器 + +组件通过使用@LocalStorageLink(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立双向数据绑定。当创建包含@LocalStorageLink的状态变量的组件时,该状态变量的值将会使用LocalStorage中的值进行初始化。如果LocalStorage中未定义初始值,将使用@LocalStorageLink定义的初始值。在UI组件中对@LocalStorageLink的状态变量所做的更改将同步到LocalStorage中,并从LocalStorage同步到Ability下的组件中。 + +## @LocalStorageProp装饰器 + +组件通过使用LocalStorageProp(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立单向数据绑定。当创建包含@LocalStorageProp的状态变量的组件时,该状态变量的值将使用LocalStorage中的值进行初始化。LocalStorage中的属性值的更改会导致当前Ability下的所有UI组件进行状态更新。 + +> **说明:** 创建LocalStorage实例时如未定义初始值,可以使用组件内@LocalStorageLink和@LocalStorageProp的初始值。如果定义时给定了初始值,那么不会再使用@LocalStorageLink和@LocalStorageProp的初始值。 + +### 示例1(在一个Ability创建的LocalStorage) + +LocalStorage通过loadContent接口加载,接口详见[loadContent](../reference/apis/js-apis-window.md#loadcontent9-1)。 + +``` +import Ability from '@ohos.application.Ability' +export default class MainAbility extends Ability { + storage : LocalStorage + onCreate() { + this.storage = new LocalStorage(); + this.storage.setOrCreate("storageSimpleProp",121); + console.log("[Demo MainAbility onCreate]"); + } + onDestroy() { + console.log("[Demo MainAbility onDestroy]") + } + onWindowStageCreate(windowStage) { + // storage作为参数传递给loadContent接口。 + windowStage.loadContent("pages/index",this.storage) + } + onWindowStageDestroy() { + console.log("[Demo] MainAbility onWindoeStageDestroy") + } + onForeground() { + console.log("[Demo] MainAbility onForeground") + } + onBackground() { + console.log("[Demo] MainAbility onBackground") + } +} +``` + +@Component组件获取数据 + +``` +let storage = LocalStorage.GetShared() +@Entry(storage) +@Component +struct LocalStorageComponent { + @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0 + build() { + Column(){ + Text(this.simpleVarName.toString()) + .onClick(()=>{ + this.simpleVarName +=1; + }) + Text(JSON.stringify(this.simpleVarName)) + .fontSize(50) + } + .height(500) + } +} +``` + +### 示例2(在Entry页面定义LocalStorage) + +``` +let storage = new LocalStorage({"PropA":47}); +@Entry(storage) +@Component +struct ComA { + @LocalStorageLink("PropA") storLink: number = 1; + build() { + Column() { + Text(`Parent from LocalStorage ${ this.storLink }`) + .onClick(()=>this.storLink+=1) + Child() + } + } +} + + +@Component +struct Child{ + @LocalStorageLink("PropA") storLink: number = 1; + build() { + Text(`Parent from LocalStorage ${ this.storLink }`) + .onClick(()=>this.storLink+=1) + } +} +``` + +## PersistentStorage + +PersistentStorage类提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。 + +> **说明:** +> +> - PersistProp接口使用时,需要保证输入对应的key应当在AppStorage存在。 +> - DeleteProp接口使用时,只能对本次启动已经link过的数据生效。 + +```ts +// xxx.ets +PersistentStorage.PersistProp("highScore", "0"); + +@Entry +@Component +struct PersistentComponent { + @StorageLink('highScore') highScore: string = '0' + @State currentScore: number = 0 + build() { + Column() { + if (this.currentScore === Number(this.highScore)) { + Text(`new highScore : ${this.highScore}`) + } + Button() { + Text(`goal!, currentScore : ${this.currentScore}`) + .fontSize(10) + }.onClick(() => { + this.currentScore++ + if (this.currentScore > Number(this.highScore)) { + this.highScore = this.currentScore.toString() + } + }) + } + } +} +``` + + ![PersistentStorage](figures/PersistentStorage.gif) + +## Environment + +Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态属性,这些属性描述了应用程序运行的设备环境。Environment及其属性是不可变的,所有属性值类型均为简单类型。如下示例展示了从Environment获取语音环境: + +``` +Environment.EnvProp("accessibilityEnabled", "default"); +var enable = AppStorage.Get("accessibilityEnabled"); +``` + +accessibilityEnabled是Environment提供默认系统变量识别符。首先需要将对应系统属性绑定到AppStorage中,再通过AppStorage中的方法或者装饰器访问对应系统的属性数据。 diff --git a/zh-cn/application-dev/quick-start/arkts-state-mgmt-concepts.md b/zh-cn/application-dev/quick-start/arkts-state-mgmt-concepts.md new file mode 100644 index 0000000000000000000000000000000000000000..b4a1c095ed531dec3796b3133673d96243b05906 --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-state-mgmt-concepts.md @@ -0,0 +1,30 @@ +# 基本概念 + +ArkTS提供了多维度的状态管理机制,在UI开发框架中,和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之前,也可以时全局范围内的传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的利用这些能力来实现数据和UI的联动。 + + +![](figures/CoreSpec_figures_state-mgmt-overview.png) + + +## 页面级变量的状态管理 + +| 装饰器 | 装饰内容 | 说明 | +| ----------- | ------------------------- | ------------------------------------------------------------ | +| @State | 基本数据类型,类,数组 | 修饰的状态数据被修改时会触发组件的build方法进行UI界面更新。 | +| @Prop | 基本数据类型 | 修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,更新当前组件的UI。 | +| @Link | 基本数据类型,类,数组 | 父子组件之间的双向数据绑定,父组件的内部状态数据作为数据源,任何一方所做的修改都会反映给另一方。 | +| @Observed | 类 | @Observed应用于类,表示该类中的数据变更被UI页面管理。 | +| @ObjectLink | 被@Observed所装饰类的对象 | 装饰的状态数据被修改时,在父组件或者其他兄弟组件内与它关联的状态数据所在的组件都会更新UI。 | +| @Consume | 基本数据类型,类,数组 | @Consume装饰的变量在感知到@Provide装饰的变量更新后,会触发当前自定义组件的重新渲染。 | +| @Provide | 基本数据类型,类,数组 | @Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。 | + +## 应用级变量的状态管理 + +AppStorage是整个UI应用程序状态的中心“数据库”,UI框架会针对应用程序创建单例AppStorage对象,并提供相应的装饰器和接口供应用程序使用。 + +- @StorageLink:@StorageLink(name)的原理类似于@Consume(name),不同的是,该给定名称的链接对象是从AppStorage中获得的,在UI组件和AppStorage之间建立双向绑定同步数据。 +- @StorageProp:@StorageProp(name)将UI组件属性与AppStorage进行单向同步,AppStorage中值的更改会更新组件中的属性,但UI组件无法更改AppStorage中的属性值。 +- AppStorage还提供用于业务逻辑实现的API,用于添加、读取、修改和删除应用程序的状态属性,此API所做的更改会导致修改的状态数据同步到UI组件上进行UI更新。 +- PersistentStorage类提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。 +- Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态属性,这些属性描述了应用程序运行的设备环境。 + diff --git a/zh-cn/application-dev/quick-start/arkts-state-mgmt-page-level.md b/zh-cn/application-dev/quick-start/arkts-state-mgmt-page-level.md new file mode 100644 index 0000000000000000000000000000000000000000..586f3f22473f4e0d3f9d4068d134a893268756fe --- /dev/null +++ b/zh-cn/application-dev/quick-start/arkts-state-mgmt-page-level.md @@ -0,0 +1,478 @@ +# 页面级变量的状态管理 + +@State、@Prop、@Link、@Provide、Consume、@ObjectLink、@Observed和@Watch用于管理页面级变量的状态。 + +## @State + +@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。 + +@State状态数据具有以下特征: + + +- 支持多种类型:允许class、number、boolean、string强类型的按值和按引用类型。允许这些强类型构成的数组,即Array<class>、Array<string>、Array<boolean>、Array<number>。不允许object和any。 +- 支持多实例:组件不同实例的内部状态数据独立。 +- 内部私有:标记为@State的属性是私有变量,只能在组件内访问。 +- 需要本地初始化:必须为所有@State变量分配初始值,将变量保持未初始化可能导致框架行为未定义。 +- 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态属性的初始值。 + +**示例:** + +在下面的示例中: + + +- 用户定义的组件MyComponent定义了@State状态变量count和title。如果count或title的值发生变化,则执行MyComponent的build方法来重新渲染组件; + +- EntryComponent中有多个MyComponent组件实例,第一个MyComponent内部状态的更改不会影响第二个MyComponent; + +- 创建MyComponent实例时通过变量名给组件内的变量进行初始化,如: + ```ts + MyComponent({title: {value: 'Hello, World 2'}, count: 7}) + ``` + +```ts +// xxx.ets +class Model { + value: string + constructor(value: string) { + this.value = value + } +} + +@Entry +@Component +struct EntryComponent { + build() { + Column() { + MyComponent({count: 1, increaseBy: 2}) // MyComponent1 in this document + MyComponent({title: {value: 'Hello, World 2'}, count: 7}) //MyComponent2 in this document + } + } +} + +@Component +struct MyComponent { + @State title: Model = {value: 'Hello World'} + @State count: number = 0 + private toggle: string = 'Hello World' + private increaseBy: number = 1 + + build() { + Column() { + Text(`${this.title.value}`).fontSize(30) + Button() { + Text(`Click to change title`).fontSize(20).fontColor(Color.White) + }.onClick(() => { + this.title.value = (this.toggle == this.title.value) ? 'Hello World' : 'Hello UI' + }) // Modify the internal state of MyComponent using the anonymous method. + + Button() { + Text(`Click to increase count=${this.count}`).fontSize(20).fontColor(Color.White) + }.onClick(() => { + this.count += this.increaseBy + }) // Modify the internal state of MyComponent using the anonymous method. + } + } +} +``` + +![@state1](figures/@state.png) + +## @Prop + +@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。 + +@Prop状态数据具有以下特征: + +- 支持简单类型:仅支持number、string、boolean简单类型; +- 私有:仅在组件内访问; +- 支持多个实例:一个组件中可以定义多个标有@Prop的属性; +- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。 + +**示例:** + +在下面的示例中,当按“+1”或“-1”按钮时,父组件状态发生变化,重新执行build方法,此时将创建一个新的CountDownComponent组件。父组件的countDownStartValue状态属性被用于初始化子组件的@Prop变量,当按下子组件的“Try again”按钮时,其@Prop变量count将被更改,CountDownComponent重新渲染。但是count值的更改不会影响父组件的countDownStartValue值。 + +```ts +// xxx.ets +@Entry +@Component +struct ParentComponent { + @State countDownStartValue: number = 10 // 10 Nuggets default start value in a Game + build() { + Column() { + Text(`Grant ${this.countDownStartValue} nuggets to play.`) + Button() { + Text('+1 - Nuggets in New Game') + }.onClick(() => { + this.countDownStartValue += 1 + }) + Button() { + Text('-1 - Nuggets in New Game') + }.onClick(() => { + this.countDownStartValue -= 1 + }) + // 创建子组件时,必须在构造函数参数中提供其@Prop变量的初始值,同时初始化常规变量CostOfOneAttump(非Prop) + CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2}) + } + } +} + +@Component +struct CountDownComponent { + @Prop count: number + private costOfOneAttempt: number + + build() { + Column() { + if (this.count > 0) { + Text(`You have ${this.count} Nuggets left`) + } else { + Text('Game over!') + } + + Button() { + Text('Try again') + }.onClick(() => { + this.count -= this.costOfOneAttempt + }) + } + } +} +``` + +> **说明:** 创建新组件实例时,必须初始化其所有@Prop变量。 + +## @Link + +@Link装饰的变量可以和父组件的@State变量建立双向数据绑定: + +- 支持多种类型:@Link变量的值与@State变量的类型相同,即class、number、string、boolean或这些类型的数组; +- 私有:仅在组件内访问; +- 单个数据源:初始化@Link变量的父组件的变量必须是@State变量; +- 双向通信:子组件对@Link变量的更改将同步修改父组件的@State变量; +- 创建自定义组件时需要将变量的引用传递给@Link变量,在创建组件的新实例时,必须使用命名参数初始化所有@Link变量。@Link变量可以使用@State变量或@Link变量的引用进行初始化,@State变量可以通过`'$'`操作符创建引用。 + +> 说明: @Link变量不能在组件内部进行初始化 + +**简单类型示例:** + +@Link语义是从`'$'`操作符引出,即`$isPlaying`是`this.isPlaying`内部状态的双向数据绑定。当单击PlayButton时,PlayButton的Image组件和Text组件将同时进行刷新。 + +```ts +// xxx.ets +@Entry +@Component +struct Player { + @State isPlaying: boolean = false + build() { + Column() { + PlayButton({buttonPlaying: $isPlaying}) + Text(`Player is ${this.isPlaying? '':'not'} playing`) + } + } +} + +@Component +struct PlayButton { + @Link buttonPlaying: boolean + build() { + Column() { + Button() { + Image(this.buttonPlaying? 'play.png' : 'pause.png') + }.onClick(() => { + this.buttonPlaying = !this.buttonPlaying + }) + } + } +} +``` + +**复杂类型示例:** + +```ts +// xxx.ets +@Entry +@Component +struct Parent { + @State arr: number[] = [1, 2, 3] + build() { + Column() { + Child({items: $arr}) + ForEach(this.arr, + item => Text(`${item}`), + item => item.toString()) + } + } +} + +@Component +struct Child { + @Link items: number[] + build() { + Column() { + Button() { + Text('Button1: push') + }.onClick(() => { + this.items.push(100) + }) + Button() { + Text('Button2: replace whole item') + }.onClick(() => { + this.items = [100, 200, 300] + }) + } + } +} +``` + +## @Link、@State和@Prop结合使用示例 + +下面示例中,ParentView包含ChildA和ChildB两个子组件,ParentView的状态变量counter分别初始化ChildA和ChildB。 + +- ChildB使用@Link建立双向状态绑定。当ChildB修改counterRef状态变量值时,该更改将同步到ParentView和ChildA共享; +- ChildA使用@Prop建立从ParentView到自身的单向状态绑定。当ChildA修改状态时,ChildA将重新渲染,但该更改不会传达给ParentView和ChildB。 + +```ts +// xxx.ets +@Entry +@Component +struct ParentView { + @State counter: number = 0 + build() { + Column() { + ChildA({counterVal: this.counter}) // pass by value + ChildB({counterRef: $counter}) // $ creates a Reference that can be bound to counterRef + } + } +} + +@Component +struct ChildA { + @Prop counterVal: number + build() { + Button() { + Text(`ChildA: (${this.counterVal}) + 1`) + }.onClick(() => {this.counterVal+= 1}) + } +} + +@Component +struct ChildB { + @Link counterRef: number + build() { + Button() { + Text(`ChildB: (${this.counterRef}) + 1`) + }.onClick(() => {this.counterRef+= 1}) + } +} +``` + +## Observed和ObjectLink数据管理 + +当开发者需要在子组件中针对父组件的一个变量(parent_a)设置双向同步时,开发者可以在父组件中使用\@State装饰变量(parent_a),并在子组件中使用@Link装饰相应的变量(child_a)。这样的话,不仅可以实现父组件与单个子组件之间的数据同步,也可以实现父组件与多个子组件之间的数据同步。如下图所示,可以看到,父子组件针对ClassA类型的变量设置了双向同步,那么当子组件1中变量的属性c的值变化时,会通知父组件同步变化,而当父组件中属性c的值变化时,会通知所有子组件同步变化。 + +![zh-cn_image_0000001251090821](figures/zh-cn_image_0000001251090821.png) + +然而,上述例子是针对某个数据对象进行的整体同步,而当开发者只想针对父组件中某个数据对象的部分信息进行同步时,使用@Link就不能满足要求。如果这些部分信息是一个类对象,就可以使用@ObjectLink配合@Observed来实现,如下图所示。 + +![zh-cn_image_0000001206450834](figures/zh-cn_image_0000001206450834.png) + +### 设置要求 + +- @Observed 用于类,@ObjectLink 用于变量。 + +- @ObjectLink装饰的变量类型必须为类(class type)。 + - 类要被\@Observed装饰器所装饰。 + - 不支持简单类型参数,可以使用@Prop进行单向同步。 + +- @ObjectLink装饰的变量是不可变的(immutable)。 + - 属性的改动是被允许的,当改动发生时,如果同一个对象被多个@ObjectLink变量所引用,那么所有拥有这些变量的自定义组件都会被通知去重新渲染。 + +- @ObjectLink装饰的变量不可设置默认值。 + - 必须让父组件中有一个由@State、@Link、@StorageLink、@Provide或@Consume所装饰变量参与的TS表达式进行初始化。 + +- @ObjectLink装饰的变量是私有变量,只能在组件内访问。 + + +### 示例 + +```ts +// xxx.ets +// 父组件ViewB中的类对象ClassA与子组件ViewA保持数据同步时,可以使用@ObjectLink和@Observed,绑定该数据对象的父组件和其他子组件同步更新 + +var nextID: number = 0; + +@Observed +class ClassA { + public name : string; + public c: number; + public id : number; + constructor(c: number, name: string = 'OK') { + this.name = name; + this.c = c; + this.id = nextID++; + } +} + +@Component +struct ViewA { + label : string = "ViewA1"; + @ObjectLink a: ClassA; + build() { + Row() { + Button(`ViewA [${this.label}] this.a.c= ${this.a.c} +1`) + .onClick(() => { + this.a.c += 1; + }) + }.margin({ top: 10 }) + } +} + +@Entry +@Component +struct ViewB { + @State arrA : ClassA[] = [ new ClassA(0), new ClassA(0) ]; + build() { + Column() { + ForEach (this.arrA, (item) => { + ViewA({label: `#${item.id}`, a: item}) + }, + (item) => item.id.toString() + ) + ViewA({label: `ViewA this.arrA[first]`, a: this.arrA[0]}) + ViewA({label: `ViewA this.arrA[last]`, a: this.arrA[this.arrA.length-1]}) + + Button(`ViewB: reset array`) + .margin({ top: 10 }) + .onClick(() => { + this.arrA = [ new ClassA(0), new ClassA(0) ]; + }) + Button(`ViewB: push`) + .margin({ top: 10 }) + .onClick(() => { + this.arrA.push(new ClassA(0)) + }) + Button(`ViewB: shift`) + .margin({ top: 10 }) + .onClick(() => { + this.arrA.shift() + }) + } + } +} +``` + + ![Observed](figures/Observed.gif) + +## @Consume和@Provide + +Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。Consume在感知到Provide数据的更新后,会触发当前view的重新渲染。 + +> **说明:** 使用@Provide 和@Consume时避免循环引用导致死循环。 + +表1 @Provide + +| 名称 | 说明 | +| -------------- | ------------------------------------------------------------ | +| 装饰器参数 | 是一个string类型的常量,用于给装饰的变量起别名。如果规定别名,则提供对应别名的数据更新。如果没有,则使用变量名作为别名。推荐使用@Provide("alias")这种形式。 | +| 同步机制 | @Provide的变量类似@State,可以修改对应变量进行页面重新渲染。也可以修改@Consume装饰的变量,反向修改@State变量。 | +| 初始值 | 必须制定初始值。 | +| 页面重渲染场景 | 触发页面渲染的修改:
- 基础类型(boolean,string,number)变量的改变;
- @Observed class类型变量及其属性的修改;
- 添加,删除,更新数组中的元素。 | + +表2 @Consume + +| 类型 | 说明 | +| ------ | ---------------- | +| 初始值 | 不可设置默认值。 | + +### 示例 + +```ts +// xxx.ets +@Entry +@Component +struct CompA { + @Provide("reviewVote") reviewVotes : number = 0; + + build() { + Column() { + CompB() + Button() { + Text(`${this.reviewVotes}`) + .fontSize(30) + } + .onClick(() => { + this.reviewVotes += 1; + }) + } + } +} + +@Component +struct CompB { + build() { + Column() { + CompC() + } + } +} + +@Component +struct CompC { + @Consume("reviewVote") reviewVotes : number; + build() { + Column() { + Button() { + Text(`${this.reviewVotes}`) + .fontSize(30) + } + .onClick(() => { + this.reviewVotes += 1; + }) + }.margin({ left:10, top: 10 }) + } +} +``` + +## @Watch + +@Watch用于监听状态变量的变化,语法结构为: + +``` +@State @Watch("onChanged") count : number = 0 +``` + +如上给状态变量增加一个@Watch装饰器,通过@Watch注册一个回调方法onChanged, 当状态变量count被改变时, 触发onChanged回调。 + +装饰器@State、@Prop、@Link、@ObjectLink、@Provide、@Consume、@StorageProp以及@StorageLink装饰的变量可以监听其变化。 + +``` +// xxx.ets +@Entry +@Component +struct CompA { + @State @Watch("onBasketUpdated") shopBasket : Array = [ 7, 12, 47, 3 ]; + @State totalPurchase : number = 0; + + updateTotal() : number { + let sum = 0; + this.shopBasket.forEach((i) => { sum += i; }); + // 计算新的购物篮总价值,如果超过100RMB,则适用折扣 + this.totalPurchase = (sum < 100) ? sum : 0.9 * sum; + return this.totalPurchase; + } + + // @Watch cb + onBasketUpdated(propName: string) : void { + this.updateTotal(); + } + + build() { + Column() { + Button("add to basket").onClick(() => { this.shopBasket.push(Math.round(100 * Math.random())) }) + Text(`${this.totalPurchase}`) + .fontSize(30) + } + } +} +``` \ No newline at end of file diff --git a/zh-cn/application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md b/zh-cn/application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md index 9dda93f56193bdb7494d8e25e265342356742ed8..365503a1dbec87bf575f75465aa7593dc0d9c5cd 100644 --- a/zh-cn/application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md +++ b/zh-cn/application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md @@ -6,10 +6,10 @@ HUAWEI DevEco Studio For OpenHarmony(以下简称DevEco Studio)是基于Inte [DevEco Studio](https://developer.harmonyos.com/cn/develop/deveco-studio/) 作为支撑OpenHarmony应用和服务开发的IDE,具有以下能力特点: -- **高效智能代码编辑**:支持eTS、JavaScript、C/C++等语言的代码高亮、代码智能补齐、代码错误检查、代码自动跳转、代码格式化、代码查找等功能,提升代码编写效率。更多详细信息,请参考[编辑器使用技巧](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-editor-usage-tips-0000001263360493)。 +- **高效智能代码编辑**:支持ArkTS、JavaScript、C/C++等语言的代码高亮、代码智能补齐、代码错误检查、代码自动跳转、代码格式化、代码查找等功能,提升代码编写效率。更多详细信息,请参考[编辑器使用技巧](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-editor-usage-tips-0000001263360493)。 - **低代码可视化开发**:丰富的UI界面编辑能力,支持自由拖拽组件和可视化数据绑定,可快速预览效果,所见即所得;同时支持卡片的零代码开发,降低开发门槛和提升界面开发效率。更多详细信息,请参考使用[低代码开发应用/服务](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-low-code-development-0000001218440652)。 - **多端双向实时预览**:支持UI界面代码的双向预览、实时预览、动态预览、组件预览以及多端设备预览,便于快速查看代码运行效果。更多详细信息,请参考[使用预览器预览应用/服务界面效果](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-previewing-app-service-0000001218760596)。 -- **全新构建体系**:通过Hvigor编译构建工具,一键完成应用及服务的编译和打包,更好地支持eTS/JS开发。 +- **全新构建体系**:通过Hvigor编译构建工具,一键完成应用及服务的编译和打包,更好地支持ArkTS/JS开发。 - **一站式信息获取**:基于开发者了解、学习、开发、求助的用户旅程,在DevEco Studio中提供一站式的信息获取平台,高效支撑开发者活动。 - **高效代码调试**:提供TS、JS 、C/C++代码的断点设置,单步执行、变量查看等调试能力,提升应用及服务的问题分析效率。 diff --git a/zh-cn/application-dev/ui/figures/@state.png b/zh-cn/application-dev/quick-start/figures/@state.png similarity index 100% rename from zh-cn/application-dev/ui/figures/@state.png rename to zh-cn/application-dev/quick-start/figures/@state.png diff --git a/zh-cn/application-dev/ui/figures/@state1.gif b/zh-cn/application-dev/quick-start/figures/@state1.gif similarity index 100% rename from zh-cn/application-dev/ui/figures/@state1.gif rename to zh-cn/application-dev/quick-start/figures/@state1.gif diff --git a/zh-cn/application-dev/quick-start/figures/CoreSpec_figures_state-mgmt-overview.png b/zh-cn/application-dev/quick-start/figures/CoreSpec_figures_state-mgmt-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..37ae5324808a0ab50f210907ca65a09e4456a371 Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/CoreSpec_figures_state-mgmt-overview.png differ diff --git a/zh-cn/application-dev/quick-start/figures/Observed.gif b/zh-cn/application-dev/quick-start/figures/Observed.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf1d3b2abb4925544997682c100efcb32b3ea7e4 Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/Observed.gif differ diff --git a/zh-cn/application-dev/quick-start/figures/PersistentStorage.gif b/zh-cn/application-dev/quick-start/figures/PersistentStorage.gif new file mode 100644 index 0000000000000000000000000000000000000000..8448907658c66d98d91207a51017ccd5143655ec Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/PersistentStorage.gif differ diff --git a/zh-cn/application-dev/quick-start/figures/appstorage.gif b/zh-cn/application-dev/quick-start/figures/appstorage.gif new file mode 100644 index 0000000000000000000000000000000000000000..907447553819293cf3e7e143aec39116c4166d8d Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/appstorage.gif differ diff --git a/zh-cn/application-dev/quick-start/figures/arkts-get-started.png b/zh-cn/application-dev/quick-start/figures/arkts-get-started.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a0cb91637601846855c0eaa30e0610a5a11ed6 Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/arkts-get-started.png differ diff --git a/zh-cn/application-dev/quick-start/figures/custom-dialog-demo.gif b/zh-cn/application-dev/quick-start/figures/custom-dialog-demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d0979823e13f959b2a4828f479af7bbc03f69f3 Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/custom-dialog-demo.gif differ diff --git a/zh-cn/application-dev/quick-start/figures/forEach.gif b/zh-cn/application-dev/quick-start/figures/forEach.gif new file mode 100644 index 0000000000000000000000000000000000000000..f123d33aa9d97e2e4e04a2de09f99d1758f4a4a1 Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/forEach.gif differ diff --git a/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001206450834.png b/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001206450834.png new file mode 100644 index 0000000000000000000000000000000000000000..35a5db40879212c9d90e5a02bba02e49e1158c8f Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001206450834.png differ diff --git a/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001251090821.png b/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001251090821.png new file mode 100644 index 0000000000000000000000000000000000000000..69aec480939a34e310d8fbeead6a8e33644bb11b Binary files /dev/null and b/zh-cn/application-dev/quick-start/figures/zh-cn_image_0000001251090821.png differ diff --git a/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md b/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md index 12c658c75628e84883cdecf837d2a290a79d4d20..0228f0021304d05029e605cb93e9ac83a255ed1e 100644 --- a/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md +++ b/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md @@ -1,4 +1,4 @@ -# 基于eTS的声明式开发范式 +# 基于ArkTS的声明式开发范式 - 组件通用信息 - 通用事件 diff --git a/zh-cn/application-dev/ui/Readme-CN.md b/zh-cn/application-dev/ui/Readme-CN.md index de85a882c0692bc2d2962070638d6f9187210192..31ff7059e958146834ba8746525e70313770c564 100755 --- a/zh-cn/application-dev/ui/Readme-CN.md +++ b/zh-cn/application-dev/ui/Readme-CN.md @@ -1,7 +1,7 @@ # UI开发 - [方舟开发框架(ArkUI)概述](arkui-overview.md) -- UI开发(基于eTS的声明式开发范式) +- UI开发(基于ArkTS的声明式开发范式) - [概述](ui-ts-overview.md) - 框架说明 - 文件组织 @@ -11,49 +11,11 @@ - [资源文件的分类](ui-ts-basic-resource-file-categories.md) - [资源访问](ts-resource-access.md) - [像素单位](ts-pixel-units.md) - - 声明式语法 - - [描述规范使用说明](ts-syntax-intro.md) - - 通用UI描述规范 - - [基本概念](ts-general-ui-concepts.md) - - 声明式UI描述规范 - - [无构造参数配置](ts-parameterless-configuration.md) - - [必选参数构造配置](ts-configuration-with-mandatory-parameters.md) - - [属性配置](ts-attribution-configuration.md) - - [事件配置](ts-event-configuration.md) - - [子组件配置](ts-child-component-configuration.md) - - 组件化 - - [@Component](ts-component-based-component.md) - - [@Entry](ts-component-based-entry.md) - - [@Preview](ts-component-based-preview.md) - - [@Builder](ts-component-based-builder.md) - - [@Extend](ts-component-based-extend.md) - - [@CustomDialog](ts-component-based-customdialog.md) - - [@Styles](ts-component-based-styles.md) - - UI状态管理 - - [基本概念](ts-ui-state-mgmt-concepts.md) - - 管理组件拥有的状态 - - [@State](ts-component-states-state.md) - - [@Prop](ts-component-states-prop.md) - - [@Link](ts-component-states-link.md) - - 管理应用程序的状态 - - [应用程序的数据存储](ts-application-states-appstorage.md) - - [Ability数据存储](ui-ts-local-storage.md) - - [持久化数据管理](ts-application-states-apis-persistentstorage.md) - - [环境变量](ts-application-states-apis-environment.md) - - 其他类目的状态管理 - - [Observed和ObjectLink数据管理](ts-other-states-observed-objectlink.md) - - [@Consume和@Provide数据管理](ts-other-states-consume-provide.md) - - [@Watch](ts-other-states-watch.md) - - 渲染控制语法 - - [条件渲染](ts-rending-control-syntax-if-else.md) - - [循环渲染](ts-rending-control-syntax-foreach.md) - - [数据懒加载](ts-rending-control-syntax-lazyforeach.md) + - 深入理解组件化 - - [build函数](ts-function-build.md) - [自定义组件初始化](ts-custom-component-initialization.md) - [自定义组件生命周期回调函数](ts-custom-component-lifecycle-callbacks.md) - [组件创建和重新初始化示例](ts-component-creation-re-initialization.md) - - [语法糖](ts-syntactic-sugar.md) - 常见组件开发指导 - [Button开发指导](ui-ts-basic-components-button.md) - [Web开发指导](ui-ts-components-web.md) @@ -71,7 +33,7 @@ - [构建食物分类Grid布局](ui-ts-building-category-grid-layout.md) - [页面跳转与数据传递](ui-ts-page-redirection-data-transmission.md) - [性能提升的推荐方法](ts-performance-improvement-recommendation.md) - + - UI开发(兼容JS的类Web开发范式) - [概述](ui-js-overview.md) - 框架说明 diff --git a/zh-cn/application-dev/ui/arkui-overview.md b/zh-cn/application-dev/ui/arkui-overview.md index b9d83108fd0b84b09fa9053225cb9dda80335482..29401d4b008f8810e31622525262dea14569c61f 100644 --- a/zh-cn/application-dev/ui/arkui-overview.md +++ b/zh-cn/application-dev/ui/arkui-overview.md @@ -1,42 +1,62 @@ # 方舟开发框架概述 -## 框架介绍 - -方舟开发框架(简称:ArkUI),是一套UI开发框架,提供开发者进行应用UI开发时所必需的能力。 +方舟开发框架(简称:ArkUI),是一套构建OpenHarmony应用界面的UI开发框架,它提供了极简的UI语法与包括UI组件、动画机制、事件交互等在内的UI开发基础设施,以满足应用开发者的可视化界面开发需求。 ## 基本概念 -- 组件:组件是界面搭建与显示的最小单位。开发者通过多种组件的组合,构建出满足自身应用诉求的完整界面。 +- **组件**:组件是界面搭建与显示的最小单位。开发者通过多种组件的组合,构建出满足自身应用诉求的完整界面。 -- 页面:page页面是方舟开发框架最小的调度分割单位。开发者可以将应用设计为多个功能页面,每个页面进行单独的文件管理,并通过路由API实现页面的调度管理,以实现应用内功能的解耦。 +- **页面**:page页面是方舟开发框架最小的调度分割单位。开发者可以将应用设计为多个功能页面,每个页面进行单独的文件管理,并通过[页面路由](../reference/apis/js-apis-router.md)API完成页面间的调度管理,以实现应用内功能的解耦。 ## 主要特征 -- UI组件:方舟开发框架不仅提供了多种基础组件, 例如文本、图片、按钮等 ,也提供了支持视频播放能力的媒体组件。并且针对不同类型设备进行了组件设计,提供了组件在不同平台上的样式适配能力,此种组件称为“多态组件”。 +- **UI组件**:方舟开发框架内置了丰富的多态组件,包括文本、图片、按钮等基础组件,可包含一个或多个子组件的容器组件,满足开发者自定义绘图需求的绘制组件,以及提供视频播放能力的媒体组件等。其中“多态”是指组件针对不同类型设备进行了设计,提供了在不同平台上的样式适配能力。 -- 布局:UI界面设计离不开布局的参与。方舟开发框架提供了多种布局方式,不仅保留了经典的弹性布局能力,也提供了列表、宫格、栅格布局和适应多分辨率场景开发的原子布局能力。 +- **布局**:UI界面设计离不开布局的参与。方舟开发框架提供了多种布局方式,不仅保留了经典的弹性布局能力,也提供了列表、宫格、栅格布局和适应多分辨率场景开发的原子布局能力。 -- 动画:方舟开发框架对于UI界面的美化,除了组件内置动画效果外,也提供了属性动画、转场动画和自定义动画能力。 +- **动画**:方舟开发框架对于UI界面的美化,除了组件内置动画效果外,也提供了属性动画、转场动画和自定义动画能力。 -- 绘制:方舟开发框架提供了多种绘制能力,以满足开发者绘制自定义形状的需求,支持图形绘制、颜色填充、文本绘制、图片绘制等。 +- **绘制**:方舟开发框架提供了多种绘制能力,以满足开发者的自定义绘图需求,支持绘制形状、颜色填充、绘制文本、变形与裁剪、嵌入图片等。 -- 交互事件:方舟开发框架提供了多种交互能力,满足应用在不同平台通过不同输入设备均可正常进行UI交互响应,默认适配了触摸手势、遥控器、鼠标等输入操作,同时也提供事件通知能力。 +- **交互事件**:方舟开发框架提供了多种交互能力,以满足应用在不同平台通过不同输入设备进行UI交互响应的需求,默认适配了触摸手势、遥控器按键输入、键鼠输入,同时提供了相应的事件回调以便开发者添加交互逻辑。 -- 平台API通道:方舟开发框架提供了API扩展机制,平台能力通过此种机制进行封装,提供风格统一的JS接口。 +- **平台API通道**:方舟开发框架提供了API扩展机制,可通过该机制对平台能力进行封装,提供风格统一的JS接口。 -- 两种开发范式:方舟开发框架针对不同目的和技术背景的开发者提供了两种开发范式,分别是基于eTS的声明式开发范式(简称“声明式开发范式”)和兼容JS的类Web开发范式(简称“类Web开发范式”)。 +- **两种开发范式**:方舟开发框架针对不同的应用场景以及不同技术背景的开发者提供了两种开发范式,分别是[基于ArkTS的声明式开发范式](./ui-ts-overview.md)(简称“声明式开发范式”)和[兼容JS的类Web开发范式](./ui-js-overview.md)(简称“类Web开发范式”)。 - | 开发范式名称 | 简介 | 适用场景 | 适用人群 | - | -------- | ---------------------------------------- | ---------------- | ------------------- | - | 声明式开发范式 | 采用TS语言并进行声明式UI语法扩展,从组件、动效和状态管理三个维度提供了UI绘制能力。UI开发更接近自然语义的编程方式,让开发者直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。同时,选用有类型标注的TS语言,引入编译期的类型校验。 | 复杂度较大、团队合作度较高的程序 | 移动系统应用开发人员、系统应用开发人员 | - | 类Web开发范式 | 采用经典的HML、CSS、JavaScript三段式开发方式。使用HML标签文件进行布局搭建,使用CSS文件进行样式描述,使用JavaScript文件进行逻辑处理。UI组件与数据之间通过单向数据绑定的方式建立关联,当数据发生变化时,UI界面自动触发更新。此种开发方式,更接近Web前端开发者的使用习惯,快速将已有的Web应用改造成方舟开发框架应用。 | 界面较为简单的中小型应用和卡片 | Web前端开发人员 | + | 开发范式名称 | 简介 | 适用场景 | 适用人群 | + | -------------- | ------------------------------------------------------------ | -------------------------------- | -------------------------------------- | + | 声明式开发范式 | 采用基于TypeScript进行声明式UI语法扩展而来的[ArkTS语言](../quick-start/arkts-get-started.md),从组件、动画和状态管理三个维度提供了UI绘制能力。声明式开发范式更接近自然语义的编程方式,让开发者直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。 | 复杂度较大、团队合作度较高的程序 | 移动系统应用开发人员、系统应用开发人员 | + | 类Web开发范式 | 采用经典的HML、CSS、JavaScript三段式开发方式,使用HML标签文件进行布局搭建,使用CSS文件进行样式描述,使用JavaScript文件进行逻辑处理。UI组件与数据之间通过单向数据绑定的方式建立关联,当数据发生变化时,UI界面自动触发刷新。该开发方式更接近Web前端开发者的使用习惯,便于快速将已有的Web应用改造成方舟开发框架应用。 | 界面较简单的中小型应用和卡片 | Web前端开发人员Web前端开发人员 | -### 框架结构 +## 框架结构 ![zh-cn_image_0000001183709904](figures/zh-cn_image_0000001183709904.png) -从上图可以看出,类Web开发范式与声明式开发范式的UI后端引擎和语言运行时是共用的,其中,UI后端引擎实现了方舟开发框架的六种基本能力。声明式开发范式无需JS Framework进行页面DOM管理,渲染更新链路更为精简,占用内存更少,因此更推荐开发者选用声明式开发范式来搭建应用UI界面。 \ No newline at end of file +从上图可以看出,类Web开发范式与声明式开发范式的UI后端引擎和语言运行时是共用的,其中,UI后端引擎实现了方舟开发框架的六种基本能力。声明式开发范式无需JS Framework进行页面DOM管理,渲染更新链路更为精简,占用内存更少,因此更推荐开发者选用声明式开发范式来搭建应用UI界面。 + +## UI与Ability框架的关系 + +Ability也是OpenHarmony应用的重要组成部分,[Ability框架](../ability/ability-brief.md)包括FA模型与Stage模型两种模型。下表给出了Ability框架的两种模型分别与方舟开发框架的两种开发范式的关系。 + +**FA模型:** + +| 类型 | UI开发范式 | 说明 | +| -------- | -------------- | ------------------------------------------------------------ | +| 应用 | 类web开发范式 | UI开发语言:使用hml/css/js 业务入口:使用固定文件名app.ets(Page类型Ability)/service.ts(Service类型Ability)/data.ts(Data类型Ability) 业务逻辑语言:js/ts | +| | 声明式开发范式 | UI开发语言:ArkTS 业务入口:使用固定文件名app.ets(Page类型Ability)/service.ts(Service类型Ability)/data.ts(Data类型Ability) 业务逻辑语言:js/ts | +| 服务卡片 | 类web开发范式 | UI开发语言:卡片显示使用hml+css+json(action) 业务入口:form.ts 卡片业务逻辑语言:js/ts | +| | 声明式开发范式 | 当前不支持 | + +**Stage模型:** + +| 类型 | UI开发范式 | 说明 | +| -------- | -------------- | ------------------------------------------------------------ | +| 应用 | 类web开发范式 | 当前不支持 | +| | 声明式开发范式 | UI开发语言:ArkTS 业务入口:应用模型基于ohos.application.Ability/ExtensionAbility等派生 业务逻辑语言:ts | +| 服务卡片 | 类web开发范式 | UI开发语言:卡片显示使用hml+css+json(action) 业务入口:从FormExtensionAbility派生 业务逻辑语言:ts | +| | 声明式开发范式 | 当前不支持 | \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ts-application-states-apis-environment.md b/zh-cn/application-dev/ui/ts-application-states-apis-environment.md deleted file mode 100644 index 54c3703e6bf98ac25926741fe4fdc18bf25c3bbe..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-application-states-apis-environment.md +++ /dev/null @@ -1,32 +0,0 @@ -# 环境变量 - -Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态属性,这些属性描述了应用程序运行的设备环境。Environment及其属性是不可变的,所有属性值类型均为简单类型。如下示例展示了从Environment获取语音环境: - - -```ts -Environment.EnvProp("accessibilityEnabled", "default"); -var enable = AppStorage.Get("accessibilityEnabled"); -``` - -accessibilityEnabled是Environment提供默认系统变量识别符。首先需要将对应系统属性绑定到AppStorage中,再通过AppStorage中的方法或者装饰器访问对应系统的属性数据。 - - -## Environment接口 - -| key | 参数 | 返回值 | 说明 | -| -------- | ---------------------------------------- | ------- | ---------------------------------------- | -| EnvProp | key: string,
defaultValue: any | boolean | 关联此系统项到AppStorage中,建议在app启动时使用此接口。如果该属性在AppStorage已存在,返回false。请勿使用AppStorage中的变量,在调用此方法关联环境变量。 | -| EnvProps | keys: {
key: string,
defaultValue: any
}[] | void | 关联此系统项数组到AppStorage中。 | -| Keys | Array<string> | number | 返回关联的系统项。 | - - -## Environment内置的环境变量 - -| key | 类型 | 说明 | -| -------------------- | --------------- | ---------------------------------------- | -| accessibilityEnabled | boolean | 无障碍屏幕朗读是否启用。 | -| colorMode | ColorMode | 深浅色模式,可选值为:
- ColorMode.LIGHT:浅色模式;
- ColorMode.DARK:深色模式。 | -| fontScale | number | 字体大小比例,取值范围为[0.85, 1.45]。 | -| fontWeightScale | number | 字体权重比例,取值范围为[0.6, 1.6]。 | -| layoutDirection | LayoutDirection | 布局方向类型,可选值为:
- LayoutDirection.LTR:从左到右;
- LayoutDirection.RTL:从右到左。 | -| languageCode | string | 设置当前系统的语言,小写字母,例如zh。 | diff --git a/zh-cn/application-dev/ui/ts-application-states-apis-persistentstorage.md b/zh-cn/application-dev/ui/ts-application-states-apis-persistentstorage.md deleted file mode 100644 index 6c8c29d7ca078f56ae8fccbd14aaf61fb75931d9..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-application-states-apis-persistentstorage.md +++ /dev/null @@ -1,46 +0,0 @@ -# 持久化数据管理 - -方舟开发框架通过PersistentStorage类提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。 - - -| 方法 | 参数说明 | 返回值 | 定义 | -| ------------ | ---------------------------------------- | ------------------- | ---------------------------------------- | -| PersistProp | key : string
defaultValue: T | void | 关联命名的属性在AppStorage变为持久化数据,赋值覆盖顺序如下:
- 首先,如果该属性存在于AppStorage,将Persistent中的数据复写为AppStorage中的属性值。
- 其次,Persistent中有此命名的属性,使用Persistent中的属性值。
- 最后,以上条件均不满足,则使用defaultValue,不支持null和undefined。 | -| DeleteProp | key: string | void | 取消双向数据绑定,该属性值将从持久存储中删除。 | -| PersistProps | keys: {
key: string,
defaultValue: any
}[] | void | 关联多个命名的属性绑定。 | -| Keys | void | Array<string> | 返回所有持久化属性的标记。 | - - -> **说明:** -> - PersistProp接口使用时,需要保证输入对应的key应当在AppStorage存在。 -> -> - DeleteProp接口使用时,只能对本次启动已经link过的数据生效。 - - -```ts -// xxx.ets -PersistentStorage.PersistProp("highScore", "0"); - -@Entry -@Component -struct PersistentComponent { - @StorageLink('highScore') highScore: string = '0' - @State currentScore: number = 0 - build() { - Column() { - if (this.currentScore === Number(this.highScore)) { - Text(`new highScore : ${this.highScore}`) - } - Button() { - Text(`goal!, currentScore : ${this.currentScore}`) - .fontSize(10) - }.onClick(() => { - this.currentScore++ - if (this.currentScore > Number(this.highScore)) { - this.highScore = this.currentScore.toString() - } - }) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-application-states-appstorage.md b/zh-cn/application-dev/ui/ts-application-states-appstorage.md deleted file mode 100644 index 503d3a225b777cfb00cfb55245f69d4be5f92d45..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-application-states-appstorage.md +++ /dev/null @@ -1,101 +0,0 @@ -# 应用程序的数据存储 - -AppStorage是应用程序中的单例对象,由UI框架在应用程序启动时创建,在应用程序退出时销毁,为应用程序范围内的可变状态属性提供中央存储。AppStorage包含整个应用程序中需要访问的所有状态属性,只要应用程序保持运行,AppStorage就会保存所有属性及属性值,属性值可以通过唯一的键值进行访问。 - - -UI组件可以通过装饰器将应用程序状态数据与AppStorage进行同步,应用业务逻辑的实现也可以通过接口访问AppStorage。 - - -AppStorage的选择状态属性可以与不同的数据源或数据接收器同步,这些数据源和接收器可以是设备上的本地或远程,并具有不同的功能,如数据持久性。这样的数据源和接收器可以独立于UI在业务逻辑中实现。 - - -默认情况下,AppStorage中的属性是可变的,AppStorage还可使用不可变(只读)属性。 - - -## AppStorage接口 - -| 方法 | 参数说明 | 返回值 | 定义 | -| ----------- | ---------------------------------------- | ------------------- | ---------------------------------------- | -| SetAndLink | key: string,
defaultValue: T | @Link | 与Link接口类似,如果当前的key保存于AppStorage,则返回该key对应的value。如果该key未被创建,则创建一个对应default值的Link返回。 | -| Set | key: string,
newValue: T | void | 对已保存的key值,替换其value值。 | -| Link | key: string | @Link | 如果存在具有给定键的数据,则返回到此属性的双向数据绑定,该双向绑定意味着变量或者组件对数据的更改将同步到AppStorage,通过AppStorage对数据的修改将同步到变量或者组件。如果具有此键的属性不存在或属性为只读,则返回undefined。 | -| SetAndProp | propName: string,
defaultValue: S | @Prop | 与Prop接口类似,如果当前的key保存于AppStorage,则返回该key对应的value。如果该key未被创建,则创建一个对应default值的Prop返回。 | -| Prop | key: string | @Prop | 如果存在具有给定键的属性,则返回此属性的单向数据绑定。该单向绑定意味着只能通过AppStorage将属性的更改同步到变量或者组件。该方法返回的变量为不可变变量,适用于可变和不可变的状态属性,如果具有此键的属性不存在则返回undefined。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> prop方法对应的属性值类型为简单类型。 | -| SetOrCreate | key: string,
newValue: T | boolean | 如果已存在与给定键名字相同的属性,如果此属性可以被更改则替换其value值且返回true,否则不替换且返回false。
如果不存在存在与给定键名字相同的属性, 则创建一个键为key, 值为newValue的属性,属性值不支持null和undefined。 | -| Get | key: string | T或undefined | 通过此接口获取对应key值的value。 | -| Has | propName: string | boolean | 判断对应键值的属性是否存在。 | -| Keys | void | array<string> | 返回包含所有键的字符串数组。 | -| Delete | key: string | boolean | 删除key指定的键值对,如果存在且删除成功返回true,不存在或删除失败返回false。 | -| Clear | void | boolean | 删除所有的属性,如果当前有状态变量依旧引用此属性,则返回false。 | -| IsMutable | key: string | boolean | 返回此属性是否存在并且是否可以改变。 | - - -## AppStorage与组件同步 - -在[管理组件拥有的状态](ts-component-states-state.md)中,已经定义了如何将组件的状态变量与父组件或祖先组件中的@State装饰的状态变量同步,主要包括@Prop、@Link、@Consume。 - -本章节定义如何将组件变量与AppStorage同步,主要提供@StorageLink和@StorageProp装饰器。 - - -### @StorageLink装饰器 - -组件通过使用@StorageLink(key)装饰的状态变量,与AppStorage建立双向数据绑定,key为AppStorage中的属性键值。当创建包含@StorageLink的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。在UI组件中对@StorageLink的状态变量所做的更改将同步到AppStorage,并从AppStorage同步到任何其他绑定实例中,如PersistentStorage或其他绑定的UI组件。 - - -### @StorageProp装饰器 - -组件通过使用@StorageProp(key)装饰的状态变量,将与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StoageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中的属性值的更改会导致绑定的UI组件进行状态更新。 - - -## 示例 - -```ts -// xxx.ets - -@Entry -@Component -struct ComponentA { - @StorageLink('varA') varA: number = 2 - @StorageProp('languageCode') lang: string = 'en' - private label: string = 'count' - - aboutToAppear() { - this.label = (this.lang === 'zh') ? '数' : 'Count' - } - - build() { - Column(){ - Row({ space: 20 }) { - Button(`${this.label}: ${this.varA}`) - .onClick(() => { - AppStorage.Set('varA', AppStorage.Get('varA') + 1) - }) - Button(`lang: ${this.lang}`) - .onClick(() => { - if (this.lang === 'zh') { - AppStorage.Set('languageCode', 'en') - } else { - AppStorage.Set('languageCode', 'zh') - } - this.label = (this.lang === 'zh') ? '数' : 'Count' - }) - } - .margin({ bottom: 50 }) - Row(){ - Button(`更改@StorageLink修饰的变量:${this.varA}`).fontSize(10) - .onClick(() => { - this.varA++ - }) - }.margin({ bottom: 50 }) - Row(){ - Button(`更改@StorageProp修饰的变量:${this.lang}`).fontSize(10) - .onClick(() => { - this.lang = 'test' - }) - } - } - } -} -``` - -每次用户单击Count按钮时,this.varA变量值都会增加,此变量与AppStorage中的varA同步。每次用户单击当前语言按钮时,修改AppStorage中的languageCode,此修改会同步给this.lang变量。 diff --git a/zh-cn/application-dev/ui/ts-attribution-configuration.md b/zh-cn/application-dev/ui/ts-attribution-configuration.md deleted file mode 100644 index 64834f2571e3819a8c3cb5084b42c150f6ff6a2d..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-attribution-configuration.md +++ /dev/null @@ -1,40 +0,0 @@ -# 属性配置 - - -使用属性方法配置组件的属性,属性方法紧随组件,并用“.”运算符连接。 - - -- 配置Text组件的字体大小属性: - ```ts - Text('123') - .fontSize(12) - ``` - - -- 使用“.”操作进行链式调用并同时配置组件的多个属性,如下所示: - ```ts - Image('a.jpg') - .alt('error.jpg') - .width(100) - .height(100) - ``` - - -- 除了直接传递常量参数外,还可以传递变量或表达式,如下所示: - ```ts - // Size, count, and offset are private variables defined in the component. - Text('hello') - .fontSize(this.size) - Image('a.jpg') - .width(this.count % 2 === 0 ? 100 : 200) - .height(this.offset + 100) - ``` - - -- 对于内置组件,框架还为其属性预定义了一些枚举类型,供开发人员调用,枚举值可以作为参数传递。枚举类型必须满足参数类型要求,有关特定属性的枚举类型定义的详细信息。可以按以下方式配置Text组件的颜色和字体属性: - ```ts - Text('hello') - .fontSize(20) - .fontColor(Color.Red) - .fontWeight(FontWeight.Bold) - ``` diff --git a/zh-cn/application-dev/ui/ts-child-component-configuration.md b/zh-cn/application-dev/ui/ts-child-component-configuration.md deleted file mode 100644 index 926d1d1c4f49a35598ef46597382285468fa50fb..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-child-component-configuration.md +++ /dev/null @@ -1,47 +0,0 @@ -# 子组件配置 - - -对于支持子组件配置的组件,例如容器组件,在“{ ... }”里为组件添加子组件的UI描述。Column、Row、Stack、Button、Grid和List组件都是容器组件。 - - -- 以下是简单的Column示例: - ```ts - Column() { - Text('Hello') - .fontSize(100) - Divider() - Text(this.myText) - .fontSize(100) - .fontColor(Color.Red) - } - ``` - - -- 可以嵌套多个子组件: - ```ts - Column() { - Column() { - Button() { - Text('+ 1') - }.type(ButtonType.Capsule) - .onClick(() => console.log ('+1 clicked!')) - Image('1.jpg') - } - Divider() - Column() { - Button() { - Text('+ 2') - }.type(ButtonType.Capsule) - .onClick(() => console.log ('+2 clicked!')) - Image('2.jpg') - } - Divider() - Column() { - Button() { - Text('+ 3') - }.type(ButtonType.Capsule) - .onClick(() => console.log('+3 clicked!')) - Image('3.jpg') - } - }.alignItems(HorizontalAlign.Center) // center align components inside Column - ``` diff --git a/zh-cn/application-dev/ui/ts-component-based-component.md b/zh-cn/application-dev/ui/ts-component-based-component.md deleted file mode 100644 index fd7a8f8cab8dbb989e077d5871ee55dc013dfc95..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-based-component.md +++ /dev/null @@ -1,121 +0,0 @@ -# @Component - -@Component装饰的struct表示该结构体具有组件化能力,能够成为一个独立的组件,这种类型的组件也称为自定义组件,在build方法里描述UI结构。自定义组件具有以下特点: - - -- 可组合:允许开发人员组合使用内置组件、其他组件、公共属性和方法; -- 链式调用9+:通过链式调用通用属性改变组件样式; -- 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用; -- 生命周期:生命周期的回调方法可以在组件中配置,用于业务逻辑处理; -- 数据驱动更新:由状态变量的数据驱动,实现UI自动更新。 - - -对组件化的深入描述,请参考[深入理解组件化](ts-custom-component-initialization.md)。 - - -> **说明:** -> -> - 自定义组件必须定义build方法。 ->- 自定义组件禁止自定义构造函数。 - - -如下代码定义了MyComponent组件: - - -```ts -@Component -struct MyComponent { - build() { - Column() { - Text('my component') - .fontColor(Color.Red) - }.alignItems(HorizontalAlign.Center) // center align Text inside Column - } -} -``` - - -MyComponent的build方法会在初始渲染时执行,此外,当组件中的状态发生变化时,build方法将再次执行。 - - -以下代码使用了MyComponent组件: - - -```ts -@Component -struct ParentComponent { - build() { - Column() { - MyComponent() - Text('we use component') - .fontSize(20) - } - } -} -``` - - -可以多次使用MyComponent,并在不同的组件中进行重用: - - -```ts -@Component -struct ParentComponent { - build() { - Row() { - Column() { - MyComponent() - Text('first column') - .fontSize(20) - } - Column() { - MyComponent() - Text('second column') - .fontSize(20) - } - } - } - - aboutToAppear() { - console.log('ParentComponent: Just created, about to become rendered first time.') - } - - aboutToDisappear() { - console.log('ParentComponent: About to be removed from the UI.') - } -} -``` - -可链式调用通用属性,使组件样式多样化: - -> **说明:** 从API version 9开始支持。 -> -> 自定义组件链式调用暂不支持尾随闭包写法(在初始化自定义组件时,组件名称紧跟一个大括号“{}”形成尾随闭包场景`(Inedx(){})`。开发者可把尾随闭包看做一个容器,向其填充内容,如在闭包内增加组件`{Column(){Text("content")}` )。 - -```ts -@Entry -@Component -struct Index { - @State bannerValue: string = 'Hello,world'; - build() { - Column() { - Chind({ ChindBannerValue:$bannerValue }) - .height(60) - .width(250) - .border({ width:5, color:Color.Red, radius:10, style: BorderStyle.Dotted }) - } - } -} - -@Component -struct Chind { - @Link ChindBannerValue: string; - build() { - Column() { - Text(this.ChindBannerValue) - .fontSize(30) - } - } -} -``` - diff --git a/zh-cn/application-dev/ui/ts-component-based-customdialog.md b/zh-cn/application-dev/ui/ts-component-based-customdialog.md deleted file mode 100644 index 9d72b589762d8a952a765503a413b96dbf8c375c..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-based-customdialog.md +++ /dev/null @@ -1,51 +0,0 @@ -# @CustomDialog - -@CustomDialog装饰器用于装饰自定义弹窗。 - - -```ts -// custom-dialog-demo.ets -@CustomDialog -struct DialogExample { - controller: CustomDialogController; - action: () => void; - - build() { - Row() { - Button ("Close CustomDialog") - .onClick(() => { - this.controller.close(); - this.action(); - }) - }.padding(20) - } -} - -@Entry -@Component -struct CustomDialogUser { - dialogController : CustomDialogController = new CustomDialogController({ - builder: DialogExample({action: this.onAccept}), - cancel: this.existApp, - autoCancel: true - }); - - onAccept() { - console.log("onAccept"); - } - existApp() { - console.log("Cancel dialog!"); - } - - build() { - Column() { - Button("Click to open Dialog") - .onClick(() => { - this.dialogController.open() - }) - } - } -} -``` - - ![custom-dialog-demo](figures/custom-dialog-demo.gif) \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ts-component-based-entry.md b/zh-cn/application-dev/ui/ts-component-based-entry.md deleted file mode 100644 index 74e81fe05e1681b687a5b6827d6c41bbd903bac4..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-based-entry.md +++ /dev/null @@ -1,35 +0,0 @@ -# @Entry - -用@Entry装饰的自定义组件用作页面的默认入口组件,加载页面时,将首先创建并呈现@Entry装饰的自定义组件。 - - -> **说明:** -> 在单个源文件中,最多可以使用@Entry装饰一个自定义组件。 - - -@Entry的用法如下: - - -```ts -// Only MyComponent decorated by @Entry is rendered and displayed. "hello world" is displayed, but "goodbye" is not displayed. -@Entry -@Component -struct MyComponent { - build() { - Column() { - Text('hello world') - .fontColor(Color.Red) - } - } -} - -@Component -struct HideComponent { - build() { - Column() { - Text('goodbye') - .fontColor(Color.Blue) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-component-based-extend.md b/zh-cn/application-dev/ui/ts-component-based-extend.md deleted file mode 100644 index ff4074ff372110eba74767474c1b51cc2734a030..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-based-extend.md +++ /dev/null @@ -1,32 +0,0 @@ -# @Extend - -@Extend装饰器将新的属性函数添加到内置组件上,如Text、Column、Button等。通过@Extend装饰器可以快速定义并复用组件的自定义样式。 - - -```ts -// xxx.ets -@Extend(Text) function fancy(fontSize: number) { - .fontColor(Color.Red) - .fontSize(fontSize) - .fontStyle(FontStyle.Italic) -} - -@Entry -@Component -struct FancyUse { - build() { - Row({ space: 10 }) { - Text("Fancy") - .fancy(16) - Text("Fancy") - .fancy(24) - } - } -} -``` - - -> **说明:** -> -> - @Extend装饰器不能用在自定义组件struct定义框内。 -> - @Extend装饰器内仅支持属性函数语句。 diff --git a/zh-cn/application-dev/ui/ts-component-based-styles.md b/zh-cn/application-dev/ui/ts-component-based-styles.md deleted file mode 100644 index 288081d69ff3d0c4a7908c883319d5a4f430f7f0..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-based-styles.md +++ /dev/null @@ -1,74 +0,0 @@ -# @Styles - - - -@Styles装饰器将新的属性函数添加到基本组件上,如Text、Column、Button等。当前@Styles仅支持通用属性。通过@Styles装饰器可以快速定义并复用组件的自定义样式。 - -@Styles可以定义在组件内或组件外,在组件外定义时需在方法前添加function关键字,组件内定义时不需要添加function关键字。 - - -```ts -// xxx.ets -@Styles function globalFancy() { - .backgroundColor(Color.Red) -} - -@Entry -@Component -struct FancyUse { - @Styles componentFancy() { - .backgroundColor(Color.Blue) - } - build() { - Column({ space: 10 }) { - Text("Fancy") - .globalFancy() - .width(100) - .height(100) - .fontSize(30) - Text("Fancy") - .componentFancy() - .width(100) - .height(100) - .fontSize(30) - } - } -} -``` - -@Styles还可以在[StateStyles](../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md)属性内部使用,在组件处于不同的状态时赋予相应的属性。 - -在StateStyles内可以直接调用组件外定义的Styles,但需要通过this关键字调用组件内定义的Styles。 - -```ts -// xxx.ets -@Styles function globalFancy() { - .width(100) - .height(100) -} - -@Entry -@Component -struct FancyUse { - @Styles componentFancy() { - .width(50) - .height(50) - } - build() { - Row({ space: 10 }) { - Button() { - Text("Fancy") - } - .stateStyles({ - normal: { - .width(80) - .height(80) - }, - disabled: this.componentFancy, - pressed: globalFancy - }) - } - } -} -``` - diff --git a/zh-cn/application-dev/ui/ts-component-states-link.md b/zh-cn/application-dev/ui/ts-component-states-link.md deleted file mode 100644 index e6aef9bf933352edd56b46dfc8050cc91259b377..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-states-link.md +++ /dev/null @@ -1,137 +0,0 @@ -# @Link - -@Link装饰的变量可以和父组件的@State变量建立双向数据绑定: - - -- 支持多种类型:@Link变量的值与@State变量的类型相同,即class、number、string、boolean或这些类型的数组; - -- 私有:仅在组件内访问; - -- 单个数据源:初始化@Link变量的父组件的变量必须是@State变量; - -- 双向通信:子组件对@Link变量的更改将同步修改父组件的@State变量; - -- 创建自定义组件时需要将变量的引用传递给@Link变量,在创建组件的新实例时,必须使用命名参数初始化所有@Link变量。@Link变量可以使用@State变量或@Link变量的引用进行初始化,@State变量可以通过`'$'`操作符创建引用。 - - -> 说明: -> @Link变量不能在组件内部进行初始化。 - - -## 简单类型示例 - -```ts -// xxx.ets -@Entry -@Component -struct Player { - @State isPlaying: boolean = false - build() { - Column() { - PlayButton({buttonPlaying: $isPlaying}) - Text(`Player is ${this.isPlaying? '':'not'} playing`) - } - } -} - -@Component -struct PlayButton { - @Link buttonPlaying: boolean - build() { - Column() { - Button() { - Image(this.buttonPlaying? 'play.png' : 'pause.png') - }.onClick(() => { - this.buttonPlaying = !this.buttonPlaying - }) - } - } -} -``` - -@Link语义是从`'$'`操作符引出,即`$isPlaying`是`this.isPlaying`内部状态的双向数据绑定。当单击PlayButton时,PlayButton的Image组件和Text组件将同时进行刷新。 - - -## 复杂类型示例 - -```ts -// xxx.ets -@Entry -@Component -struct Parent { - @State arr: number[] = [1, 2, 3] - build() { - Column() { - Child({items: $arr}) - ForEach(this.arr, - item => Text(`${item}`), - item => item.toString()) - } - } -} - -@Component -struct Child { - @Link items: number[] - build() { - Column() { - Button() { - Text('Button1: push') - }.onClick(() => { - this.items.push(100) - }) - Button() { - Text('Button2: replace whole item') - }.onClick(() => { - this.items = [100, 200, 300] - }) - } - } -} -``` - -在上面的示例中,点击Button1和Button2更改父组件中显示的文本项目列表。 - - -## @Link、@State和@Prop结合使用示例 - -```ts -// xxx.ets -@Entry -@Component -struct ParentView { - @State counter: number = 0 - build() { - Column() { - ChildA({counterVal: this.counter}) // pass by value - ChildB({counterRef: $counter}) // $ creates a Reference that can be bound to counterRef - } - } -} - -@Component -struct ChildA { - @Prop counterVal: number - build() { - Button() { - Text(`ChildA: (${this.counterVal}) + 1`) - }.onClick(() => {this.counterVal+= 1}) - } -} - -@Component -struct ChildB { - @Link counterRef: number - build() { - Button() { - Text(`ChildB: (${this.counterRef}) + 1`) - }.onClick(() => {this.counterRef+= 1}) - } -} -``` - -上述示例中,ParentView包含ChildA和ChildB两个子组件,ParentView的状态变量counter分别初始化ChildA和ChildB。 - -- ChildB使用@Link建立双向状态绑定。当ChildB修改counterRef状态变量值时,该更改将同步到ParentView和ChildA共享; - -- ChildA使用@Prop建立从ParentView到自身的单向状态绑定。当ChildA修改状态时,ChildA将重新渲染,但该更改不会传达给ParentView和ChildB。 diff --git a/zh-cn/application-dev/ui/ts-component-states-prop.md b/zh-cn/application-dev/ui/ts-component-states-prop.md deleted file mode 100644 index 997bf63e91803ccfef3f03fcad26021bc28968b8..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-states-prop.md +++ /dev/null @@ -1,70 +0,0 @@ -# @Prop - -@Prop与@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。 - -@Prop状态数据具有以下特征: - - -- 支持简单类型:仅支持number、string、boolean简单类型; - -- 私有:仅在组件内访问; - -- 支持多个实例:一个组件中可以定义多个标有@Prop的属性; - -- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有@Prop变量,不支持在组件内部进行初始化。 - - -## 示例 - -```ts -// xxx.ets -@Entry -@Component -struct ParentComponent { - @State countDownStartValue: number = 10 // 10 Nuggets default start value in a Game - build() { - Column() { - Text(`Grant ${this.countDownStartValue} nuggets to play.`) - Button() { - Text('+1 - Nuggets in New Game') - }.onClick(() => { - this.countDownStartValue += 1 - }) - Button() { - Text('-1 - Nuggets in New Game') - }.onClick(() => { - this.countDownStartValue -= 1 - }) - // 创建子组件时,必须在构造函数参数中提供其@Prop变量的初始值,同时初始化常规变量CostOfOneAttump(非Prop) - CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2}) - } - } -} - -@Component -struct CountDownComponent { - @Prop count: number - private costOfOneAttempt: number - - build() { - Column() { - if (this.count > 0) { - Text(`You have ${this.count} Nuggets left`) - } else { - Text('Game over!') - } - - Button() { - Text('Try again') - }.onClick(() => { - this.count -= this.costOfOneAttempt - }) - } - } -} -``` - -在上述示例中,当按“+1”或“-1”按钮时,父组件状态发生变化,重新执行build方法,此时将创建一个新的CountDownComponent组件。父组件的countDownStartValue状态属性被用于初始化子组件的@Prop变量,当按下子组件的“Try again”按钮时,其@Prop变量count将被更改,CountDownComponent重新渲染。但是count值的更改不会影响父组件的countDownStartValue值。 - -> **说明:** -> 创建新组件实例时,必须初始化其所有@Prop变量。 diff --git a/zh-cn/application-dev/ui/ts-component-states-state.md b/zh-cn/application-dev/ui/ts-component-states-state.md deleted file mode 100644 index 154c1a5c3a488026ad05ffab82ab9eebd9fd5bf8..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-component-states-state.md +++ /dev/null @@ -1,106 +0,0 @@ -# @State - -@State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新,只能监听第一层数据的改变,内层数据的改变@State监听不到,无法触发build生命周期。 - -@State状态数据具有以下特征: - - -- 支持多种类型:允许class、number、boolean、string强类型的按值和按引用类型。允许这些强类型构成的数组,即Array<class>、Array<string>、Array<boolean>、Array<number>。不允许object和any。 - -- 支持多实例:组件不同实例的内部状态数据独立。 - -- 内部私有:标记为@State的属性是私有变量,只能在组件内访问。 - -- 需要本地初始化:必须为所有@State变量分配初始值,将变量保持未初始化可能导致框架行为未定义。 - -- 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态属性的初始值。 - - -## 简单类型的状态属性示例 - -```ts -// xxx.ets -@Entry -@Component -struct MyComponent { - @State count: number = 0 - // MyComponent provides a method for modifying the @State status data member. - private toggleClick() { - this.count += 1 - } - - build() { - Column() { - Button() { - Text(`click times: ${this.count}`) - .fontSize(10) - }.onClick(this.toggleClick.bind(this)) - } - } -} -``` - -![@state1](figures/@state1.gif) - -## 复杂类型的状态变量示例 - -```ts -// Customize the status data class. -// xxx.ets -class Model { - value: string - constructor(value: string) { - this.value = value - } -} - -@Entry -@Component -struct EntryComponent { - build() { - Column() { - MyComponent({count: 1, increaseBy: 2}) // MyComponent1 in this document - MyComponent({title: {value: 'Hello, World 2'}, count: 7}) //MyComponent2 in this document - } - } -} - -@Component -struct MyComponent { - @State title: Model = {value: 'Hello World'} - @State count: number = 0 - private toggle: string = 'Hello World' - private increaseBy: number = 1 - - build() { - Column() { - Text(`${this.title.value}`).fontSize(30) - Button() { - Text(`Click to change title`).fontSize(20).fontColor(Color.White) - }.onClick(() => { - this.title.value = (this.toggle == this.title.value) ? 'Hello World' : 'Hello UI' - }) // Modify the internal state of MyComponent using the anonymous method. - - Button() { - Text(`Click to increase count=${this.count}`).fontSize(20).fontColor(Color.White) - }.onClick(() => { - this.count += this.increaseBy - }) // Modify the internal state of MyComponent using the anonymous method. - } - } -} -``` - -![@state1](figures/@state.png) - -在上述示例中: - - -- 用户定义的组件MyComponent定义了@State状态变量count和title。如果count或title的值发生变化,则执行MyComponent的build方法来重新渲染组件; - -- EntryComponent中有多个MyComponent组件实例,第一个MyComponent内部状态的更改不会影响第二个MyComponent; - -- 创建MyComponent实例时通过变量名给组件内的变量进行初始化,如: - ```ts - MyComponent({title: {value: 'Hello, World 2'}, count: 7}) - ``` diff --git a/zh-cn/application-dev/ui/ts-configuration-with-mandatory-parameters.md b/zh-cn/application-dev/ui/ts-configuration-with-mandatory-parameters.md deleted file mode 100644 index 17c9aa3f3fa21e28cb37de06095141bde7ec7ddf..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-configuration-with-mandatory-parameters.md +++ /dev/null @@ -1,33 +0,0 @@ -# 必选参数构造配置 - - -如果组件的接口定义中包含必选构造参数,则在组件后面的“()”中必须配置参数,参数可以使用常量进行赋值。 - - -例如: - - -- Image组件的必选参数src: - ```ts - Image('http://xyz/a.jpg') - ``` - - -- Text组件的必选参数content: - ```ts - Text('123') - ``` - - -变量或表达式也可以用于参数赋值,其中表达式返回的结果类型必须满足参数类型要求。例如,传递变量或表达式来构造Image和Text组件的参数: - - -```ts -// imagePath, where imageUrl is a private data variable defined in the component. -Image(this.imagePath) -Image('http://' + this.imageUrl) -// count is a private data variable defined in the component. -// (``) and (${}) are the template character string features supported by the TS language and comply with the -// features of the corresponding language. This specification is not limited. -Text(`count: ${this.count}`) -``` diff --git a/zh-cn/application-dev/ui/ts-event-configuration.md b/zh-cn/application-dev/ui/ts-event-configuration.md deleted file mode 100644 index d9c2274dca564d045e687e391ce791e964dd8c00..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-event-configuration.md +++ /dev/null @@ -1,36 +0,0 @@ -# 事件配置 - -通过事件方法可以配置组件支持的事件。从API Version 9开始,可以在回调函数中获取当前component关联的Context,具体用法请参考[在eTS页面中访问Context](../ability/context-userguide.md)。 - - -- 使用lambda表达式配置组件的事件方法: - ```ts - // Counter is a private data variable defined in the component. - Button('add counter') - .onClick(() => { - this.counter += 2 - }) - ``` - - -- 使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数体中的this引用包含的组件: - ```ts - // Counter is a private data variable defined in the component. - Button('add counter') - .onClick(function () { - this.counter += 2 - }.bind(this)) - ``` - - -- 使用组件的成员函数配置组件的事件方法: - ```ts - myClickHandler(): void { - // do something - } - - ... - - Button('add counter') - .onClick(this.myClickHandler) - ``` diff --git a/zh-cn/application-dev/ui/ts-framework-directory.md b/zh-cn/application-dev/ui/ts-framework-directory.md index c64f4439911f8f0580a7d9f3092c0dcda80f1481..a870ac73b27a1e3768e14966f8994c4ee2ba4757 100644 --- a/zh-cn/application-dev/ui/ts-framework-directory.md +++ b/zh-cn/application-dev/ui/ts-framework-directory.md @@ -1,7 +1,7 @@ # 目录结构 -FA应用的eTS模块(entry/src/main)的典型开发目录结构如下: +FA应用的ArkTS模块(entry/src/main)的典型开发目录结构如下: ![zh-cn_image_0000001182200571](figures/zh-cn_image_0000001182200571.png) @@ -10,7 +10,7 @@ FA应用的eTS模块(entry/src/main)的典型开发目录结构如下: **目录结构中文件分类如下:** -.ets结尾的eTS(extended TypeScript)文件,用于描述UI布局、样式、事件交互和页面逻辑。 +.ets结尾的ArkTS(extended TypeScript)文件,用于描述UI布局、样式、事件交互和页面逻辑。 **各个文件夹和文件的作用:** diff --git a/zh-cn/application-dev/ui/ts-function-build.md b/zh-cn/application-dev/ui/ts-function-build.md deleted file mode 100644 index 82d6b93c4f563e013c6d3c9b8930d4d4dca34334..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-function-build.md +++ /dev/null @@ -1,14 +0,0 @@ -# build函数 - -build函数满足Builder构造器接口定义,用于定义组件的声明式UI描述。必须遵循上述Builder接口约束,在build方法中以声明式方式进行组合自定义组件或系统内置组件,在组件创建和更新场景中都会调用build方法。 - - -```ts -interface Builder { - build: () => void -} -``` - - -> **说明:** -> build方法仅支持组合组件,使用渲染控制语法。 diff --git a/zh-cn/application-dev/ui/ts-general-ui-concepts.md b/zh-cn/application-dev/ui/ts-general-ui-concepts.md deleted file mode 100644 index 9735a4db91aff4684659e886f1b82a0effb1c4a5..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-general-ui-concepts.md +++ /dev/null @@ -1,50 +0,0 @@ -# 基本概念 - -基于eTS的声明式开发范式提供了一系列基础组件,这些组件以声明方式进行组合和扩展来描述应用程序的UI界面,并且还提供了基本的数据绑定和事件处理机制,帮助开发者实现应用交互逻辑。 - - -## HelloWorld基本示例 - -```ts -// An example of displaying Hello World. After you click the button, Hello UI is displayed. -// xxx.ets -@Entry -@Component -struct Hello { - @State myText: string = 'World' - build() { - Column() { - Text('Hello') - .fontSize(30) - Text(this.myText) - .fontSize(32) - Divider() - Button() { - Text('Click me') - .fontColor(Color.Red) - }.onClick(() => { - this.myText = 'UI' - }) - .width(500) - .height(200) - } - } -} -``` - - -## 基本概念描述 - -上述示例代码描述了简单页面的结构,并介绍了以下基本概念: - -- 装饰器:方舟开发框架定义了一些具有特殊含义的装饰器,用于装饰类、结构、方法和变量。例如,上例中的@Entry、@Component和@State都是装饰器。 - -- 自定义组件:可重用的UI单元,可以与其他组件组合,如@Component装饰的struct Hello。 - -- UI描述:声明性描述UI结构,例如build()方法中的代码块。 - -- 内置组件:框架中默认内置的基本组件和布局组件,开发者可以直接调用,如Column、Text、Divider、Button等。 - -- 属性方法:用于配置组件属性,如fontSize()、width()、height()、color()等。 - -- 事件方法:在事件方法的回调中添加组件响应逻辑。例如,为Button组件添加onClick方法,在onClick方法的回调中添加点击响应逻辑。 diff --git a/zh-cn/application-dev/ui/ts-other-states-consume-provide.md b/zh-cn/application-dev/ui/ts-other-states-consume-provide.md deleted file mode 100644 index 91a13862b2db308743db5117cce79739fefd7861..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-other-states-consume-provide.md +++ /dev/null @@ -1,73 +0,0 @@ -# @Consume和@Provide数据管理 - -Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。Consume在感知到Provide数据的更新后,会触发当前view的重新渲染。 - -表1 @Provide - -| 名称 | 说明 | -| ------- | ---------------------------------------- | -| 装饰器参数 | 是一个string类型的常量,用于给装饰的变量起别名。如果规定别名,则提供对应别名的数据更新。如果没有,则使用变量名作为别名。推荐使用@Provide("alias")这种形式。 | -| 同步机制 | @Provide的变量类似@state,可以修改对应变量进行页面重新渲染。也可以修改@Consume装饰的变量,反向修改@State变量。 | -| 初始值 | 必须制定初始值。 | -| 页面重渲染场景 | 触发页面渲染的修改:
- 基础类型(boolean,string,number)变量的改变;
- @Observed class类型变量及其属性的修改;
- 添加,删除,更新数组中的元素。 | - -表2 @Consume - -| 类型 | 说明 | -| ---- | -------- | -| 初始值 | 不可设置默认值。 | - - -> **说明:** -> 使用@Provide 和@Consume时避免循环引用导致死循环。 - - -其他属性说明与Provide一致。 - - -```ts -// xxx.ets -@Entry -@Component -struct CompA { - @Provide("reviewVote") reviewVotes : number = 0; - - build() { - Column() { - CompB() - Button() { - Text(`${this.reviewVotes}`) - .fontSize(30) - } - .onClick(() => { - this.reviewVotes += 1; - }) - } - } -} - -@Component -struct CompB { - build() { - Column() { - CompC() - } - } -} - -@Component -struct CompC { - @Consume("reviewVote") reviewVotes : number; - build() { - Column() { - Button() { - Text(`${this.reviewVotes}`) - .fontSize(30) - } - .onClick(() => { - this.reviewVotes += 1; - }) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-other-states-observed-objectlink.md b/zh-cn/application-dev/ui/ts-other-states-observed-objectlink.md deleted file mode 100644 index 7a76f0d0c4fa4a308610b992697f2c8b71f4b368..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-other-states-observed-objectlink.md +++ /dev/null @@ -1,183 +0,0 @@ -# Observed和ObjectLink数据管理 - -本章将引入两个新的装饰符@Observed和@ObjectLink: - - -- @Observed应用于类,表示该类中的数据变更被UI页面管理,例如:@Observed class ClassA {}。 - -- @ObjectLink应用于被@Observed所装饰类的对象,例如:@ObjectLink a: ClassA。 - - -## 引入动机 - -当开发者需要在子组件中针对父组件的一个变量(parent_a)设置双向同步时,开发者可以在父组件中使用\@State装饰变量(parent_a),并在子组件中使用@Link装饰相应的变量(child_a)。这样的话,不仅可以实现父组件与单个子组件之间的数据同步,也可以实现父组件与多个子组件之间的数据同步。如下图所示,可以看到,父子组件针对ClassA类型的变量设置了双向同步,那么当子组件1中变量的属性c的值变化时,会通知父组件同步变化,而当父组件中属性c的值变化时,会通知所有子组件同步变化。 - -![](figures/zh-cn_image_0000001251090821.png) - -然而,上述例子是针对某个数据对象进行的整体同步,而当开发者只想针对父组件中某个数据对象的部分信息进行同步时,使用@Link就不能满足要求。如果这些部分信息是一个类对象,就可以使用@ObjectLink配合@Observed来实现,如下图所示。 - -![](figures/zh-cn_image_0000001206450834.png) - - -## 设置要求 - -- @Observed 用于类,@ObjectLink 用于变量。 - -- @ObjectLink装饰的变量类型必须为类(class type)。 - - 类要被\@Observed装饰器所装饰。 - - 不支持简单类型参数,可以使用@Prop进行单向同步。 - -- @ObjectLink装饰的变量是不可变的(immutable)。 - - 属性的改动是被允许的,当改动发生时,如果同一个对象被多个@ObjectLink变量所引用,那么所有拥有这些变量的自定义组件都会被通知去重新渲染。 - -- @ObjectLink装饰的变量不可设置默认值。 - - 必须让父组件中有一个由@State、@Link、@StorageLink、@Provide或@Consume所装饰变量参与的TS表达式进行初始化。 - -- @ObjectLink装饰的变量是私有变量,只能在组件内访问。 - - -## 示例 - - -### 案例1 - -```ts -//父组件ViewB中的类对象ClassB,其包含的对象ClassA与子组件ViewA数据同步时,通过ObjectLink将数据c值的变化状态通知给父组件同步变化。 -@Observed -class ClassA { - public name : string; - public c: number; - constructor(c: number, name: string = 'OK') { - this.name = name; - this.c = c; - } -} - -class ClassB { - public a: ClassA; - constructor(a: ClassA) { - this.a = a; - } -} - -@Component -struct ViewA { - label : string = "ep1"; - @ObjectLink a : ClassA; - build() { - Column() { - Text(`ViewA [${this.label}]: a.c=${this.a.c}`) - .fontSize(20) - Button(`+1`) - .width(100) - .margin(2) - .onClick(() => { - this.a.c += 1; - }) - Button(`reset`) - .width(100) - .margin(2) - .onClick(() => { - this.a = new ClassA(0); // 错误:ObjectLink装饰的变量a是不可变的 - }) - } - } -} - -@Entry -@Component -struct ViewB { - @State b : ClassB = new ClassB(new ClassA(10)); - build() { - Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { - ViewA({label: "ViewA #1", a: this.b.a}) - ViewA({label: "ViewA #2", a: this.b.a}) - - Button(`ViewB: this.b.a.c += 1` ) - .width(320) - .margin(4) - .onClick(() => { - this.b.a.c += 1; - }) - Button(`ViewB: this.b.a = new ClassA(0)`) - .width(240) - .margin(4) - .onClick(() => { - this.b.a = new ClassA(0); - }) - Button(`ViewB: this.b = new ClassB(ClassA(0))`) - .width(240) - .margin(4) - .onClick(() => { - this.b = new ClassB(new ClassA(0)); - }) - } - } -} -``` - - -### 案例2 - -```ts -// 父组件ViewB中的类对象ClassA与子组件ViewA保持数据同步时,可以使用@ObjectLink和@Observed,绑定该数据对象的父组件和其他子组件同步更新 -var nextID: number = 0; -@Observed -class ClassA { - public name : string; - public c: number; - public id : number; - constructor(c: number, name: string = 'OK') { - this.name = name; - this.c = c; - this.id = nextID++; - } -} - -@Component -struct ViewA { - label : string = "ViewA1"; - @ObjectLink a: ClassA; - build() { - Row() { - Button(`ViewA [${this.label}] this.a.c= ${this.a.c} +1`) - .onClick(() => { - this.a.c += 1; - }) - }.margin({ top: 10 }) - } -} - -@Entry -@Component -struct ViewB { - @State arrA : ClassA[] = [ new ClassA(0), new ClassA(0) ]; - build() { - Column() { - ForEach (this.arrA, (item) => { - ViewA({label: `#${item.id}`, a: item}) - }, - (item) => item.id.toString() - ) - ViewA({label: `ViewA this.arrA[first]`, a: this.arrA[0]}) - ViewA({label: `ViewA this.arrA[last]`, a: this.arrA[this.arrA.length-1]}) - - Button(`ViewB: reset array`) - .margin({ top: 10 }) - .onClick(() => { - this.arrA = [ new ClassA(0), new ClassA(0) ]; - }) - Button(`ViewB: push`) - .margin({ top: 10 }) - .onClick(() => { - this.arrA.push(new ClassA(0)) - }) - Button(`ViewB: shift`) - .margin({ top: 10 }) - .onClick(() => { - this.arrA.shift() - }) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-other-states-watch.md b/zh-cn/application-dev/ui/ts-other-states-watch.md deleted file mode 100644 index b1a6feb21e920d193d44e5a8b06f8fe79bd20e4a..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-other-states-watch.md +++ /dev/null @@ -1,46 +0,0 @@ -# @Watch - -@Watch用于监听状态变量的变化,语法结构为: - - -```ts -@State @Watch("onChanged") count : number = 0 -``` - - -如上给状态变量增加一个@Watch装饰器,通过@Watch注册一个回调方法onChanged, 当状态变量count被改变时, 触发onChanged回调。 - - -装饰器@State、@Prop、@Link、@ObjectLink、@Provide、@Consume、@StorageProp以及@StorageLink装饰的变量可以监听其变化。 - - -```ts -// xxx.ets -@Entry -@Component -struct CompA { - @State @Watch("onBasketUpdated") shopBasket : Array = [ 7, 12, 47, 3 ]; - @State totalPurchase : number = 0; - - updateTotal() : number { - let sum = 0; - this.shopBasket.forEach((i) => { sum += i; }); - // 计算新的购物篮总价值,如果超过100RMB,则适用折扣 - this.totalPurchase = (sum < 100) ? sum : 0.9 * sum; - return this.totalPurchase; - } - - // @Watch cb - onBasketUpdated(propName: string) : void { - this.updateTotal(); - } - - build() { - Column() { - Button("add to basket").onClick(() => { this.shopBasket.push(Math.round(100 * Math.random())) }) - Text(`${this.totalPurchase}`) - .fontSize(30) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-parameterless-configuration.md b/zh-cn/application-dev/ui/ts-parameterless-configuration.md deleted file mode 100644 index b328a96662d96cced6ec5d664aede1f3e2bdc355..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-parameterless-configuration.md +++ /dev/null @@ -1,13 +0,0 @@ -# 无参数构造配置 - - -组件的接口定义不包含必选构造参数,组件后面的“()”中不需要配置任何内容。例如,Divider组件不包含构造参数: - - -```ts -Column() { - Text('item 1') - Divider() // No parameter configuration of the divider component - Text('item 2') -} -``` diff --git a/zh-cn/application-dev/ui/ts-pixel-units.md b/zh-cn/application-dev/ui/ts-pixel-units.md index 0385cfbf9d1a11bf7adb4ab41a09ccac536634b3..3a4c5c7e6a0ef27361f80529265cff853e5600db 100644 --- a/zh-cn/application-dev/ui/ts-pixel-units.md +++ b/zh-cn/application-dev/ui/ts-pixel-units.md @@ -78,4 +78,4 @@ struct Example { 基于像素转换,有以下相关实例可供参考: -- [像素转换(eTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/PixelUnitsDemo) +- [像素转换(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/PixelUnitsDemo) diff --git a/zh-cn/application-dev/ui/ts-rending-control-syntax-foreach.md b/zh-cn/application-dev/ui/ts-rending-control-syntax-foreach.md deleted file mode 100644 index 9ee7f145cefcf6e026edbeb881bd076f75e5aa0b..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-rending-control-syntax-foreach.md +++ /dev/null @@ -1,142 +0,0 @@ -# 循环渲染 - -开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。当循环渲染的元素较多时,会出现页面加载变慢的情况,出于性能考虑,建议使用[LazyForEach](ts-rending-control-syntax-lazyforeach.md)代替。ForEach定义如下: - - -```ts -ForEach( - arr: any[], // Array to be iterated - itemGenerator: (item: any, index?: number) => void, // child component generator - keyGenerator?: (item: any, index?: number) => string // (optional) Unique key generator, which is recommended. -) -``` - - -## ForEach - - -ForEach(arr: any[],itemGenerator: (item: any, index?: number) => void, keyGenerator?: (item: any, index?: number) => string):void - - -表1 参数说明 - -| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 | -| ------------- | ---------------------------------------- | ---- | ---- | ---------------------------------------- | -| arr | any[] | 是 | - | 必须是数组,允许空数组,空数组场景下不会创建子组件。同时允许设置返回值为数组类型的函数,例如arr.slice(1, 3),设置的函数不得改变包括数组本身在内的任何状态变量,如Array.splice、Array.sort或Array.reverse这些改变原数组的函数。 | -| itemGenerator | (item: any, index?: number) => void | 是 | - | 生成子组件的lambda函数,为给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{....}”中。 | -| keyGenerator | (item: any, index?: number) => string | 否 | - | 匿名参数,用于给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则ForEach中的所有节点都将重建。 | - - -> **说明:** -> - 必须在容器组件内使用; -> -> - 生成的子组件允许在ForEach的父容器组件中,允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中; -> -> - 子项生成器函数的调用顺序不一定和数组中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作: -> ```ts -> ForEach(anArray, item => {Text(`${++counter}. item.label`)}) -> ``` -> -> 正确的示例如下: -> -> ```ts -> ForEach(anArray.map((item1, index1) => { return { i: index1 + 1, data: item1 }; }), -> item => Text(`${item.i}. item.data.label`), -> item => item.data.id.toString()) -> ``` - - -## 示例 - -简单类型数组示例: - -```ts -// xxx.ets -@Entry -@Component -struct MyComponent { - @State arr: number[] = [10, 20, 30] - build() { - Column() { - Button() { - Text('Reverse Array') - }.onClick(() => { - this.arr.reverse() - }) - - ForEach(this.arr, // Parameter 1: array to be iterated - (item: number) => { // Parameter 2: item generator - Text(`item value: ${item}`) - Divider() - }, - (item: number) => item.toString() // Parameter 3: unique key generator, which is optional but recommended. - ) - } - } -} -``` - -复杂类型数组示例: -```ts -// xxx.ets -class Month { - year: number - month: number - days: Array - - constructor(year, month, days) { - this.year = year; - this.month = month; - this.days = days; - } -} - -@Entry -@Component -struct Calendar1 { -// simulate with 6 months - @State calendar: Month[] = [ - new Month(2020, 1, [...Array(31).keys()]), - new Month(2020, 2, [...Array(28).keys()]), - new Month(2020, 3, [...Array(31).keys()]), - new Month(2020, 4, [...Array(30).keys()]), - new Month(2020, 5, [...Array(31).keys()]), - new Month(2020, 6, [...Array(30).keys()]), - ] - - build() { - Column() { - Button('next month') - .onClick(() => { - this.calendar.shift() - this.calendar.push({ - year: 2020, - month: 7, - days: [...Array(31) - .keys()] - }) - }) - ForEach(this.calendar, - (item: Month) => { - Text('month:' + item.month) - .fontSize(30) - .padding(20) - Grid() { - ForEach(item.days, - (day: number) => { - GridItem() { - Text((day + 1).toString()) - .fontSize(30) - } - }, - (day: number) => day.toString()) - } - .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr') - .rowsGap(20) - }, - // field is used together with year and month as the unique ID of the month. - (item: Month) => (item.year * 12 + item.month).toString()) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-rending-control-syntax-if-else.md b/zh-cn/application-dev/ui/ts-rending-control-syntax-if-else.md deleted file mode 100644 index fc496c42b66c5d45e44490b5c8356123f14fafd6..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-rending-control-syntax-if-else.md +++ /dev/null @@ -1,44 +0,0 @@ -# 条件渲染 - -使用if/else进行条件渲染。 - - -> **说明:** -> - if条件语句可以使用状态变量。 -> -> - 使用if可以使子组件的渲染依赖条件语句。 -> -> - 必须在容器组件内使用。 -> -> - 某些容器组件限制子组件的类型或数量。将if放置在这些组件内时,这些限制将应用于if和else语句内创建的组件。例如,Grid组件的子组件仅支持GridItem组件,在Grid组件内使用if时,则if条件语句内仅允许使用GridItem组件。 - - -## 示例 - -使用if条件语句: - -```ts -Column() { - if (this.count > 0) { - Text('count is positive') - } -} -``` - - -使用if、else if、else条件语句: - - -```ts -Column() { - if (this.count < 0) { - Text('count is negative') - } else if (this.count % 2 === 0) { - Divider() - Text('even') - } else { - Divider() - Text('odd') - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-rending-control-syntax-lazyforeach.md b/zh-cn/application-dev/ui/ts-rending-control-syntax-lazyforeach.md deleted file mode 100644 index 7c70032decd5629764a49e0998cc12bc6285147a..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-rending-control-syntax-lazyforeach.md +++ /dev/null @@ -1,191 +0,0 @@ -# 数据懒加载 - -开发框架提供数据懒加载(LazyForEach组件)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。LazyForEach定义如下: - - -```ts -LazyForEach( - dataSource: IDataSource, // Data source to be iterated - itemGenerator: (item: any) => void, // child component generator - keyGenerator?: (item: any) => string // (optional) Unique key generator, which is recommended. -): void - -interface IDataSource { - totalCount(): number; // Get total count of data - getData(index: number): any; // Get single data by index - registerDataChangeListener(listener: DataChangeListener): void; // Register listener to listening data changes - unregisterDataChangeListener(listener: DataChangeListener): void; // Unregister listener -} - -interface DataChangeListener { - onDataReloaded(): void; // Called while data reloaded - onDataAdd(index: number): void; // Called while single data added - onDataMove(from: number, to: number): void; // Called while single data moved - onDataDelete(index: number): void; // Called while single data deleted - onDataChange(index: number): void; // Called while single data changed -} -``` - - -## 接口 - - -### LazyForEach - -LazyForEach(dataSource: IDataSource, itemGenerator: (item: any) => void, keyGenerator?: (item: any) => string):void - -表1 参数说明 - -| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 | -| ------------- | --------------------------------------- | ---- | ---- | ---------------------------------------- | -| dataSource | IDataSource | 是 | - | 实现IDataSource接口的对象,需要开发者实现相关接口。 | -| itemGenerator | (item: any) => void | 是 | - | 生成子组件的lambda函数,为给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{....}”中。 | -| keyGenerator | (item: any) => string | 否 | - | 匿名函数,用于键值生成,为给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 | - - -表2 IDataSource类型说明 - -| 名称 | 描述 | -| ---------------------------------------- | ----------- | -| totalCount(): number | 获取数据总数。 | -| getData(index: number): any | 获取索引对应的数据。 | -| registerDataChangeListener(listener:DataChangeListener): void | 注册改变数据的控制器。 | -| unregisterDataChangeListener(listener:DataChangeListener): void | 注销改变数据的控制器。 | - - -表3 DataChangeListener类型说明 - -| 名称 | 描述 | -| ---------------------------------------- | ---------------------- | -| onDataReloaded(): void | 重新加载所有数据。 | -| onDataAdded(index: number): void (deprecated) | 通知组件index的位置有数据添加。 | -| onDataMoved(from: number, to: number): void (deprecated) | 通知组件数据从from的位置移到to的位置。 | -| onDataDeleted(index: number): void (deprecated) | 通知组件index的位置有数据删除。 | -| onDataChanged(index: number): void (deprecated) | 通知组件index的位置有数据变化。 | -| onDataAdd(index: number): void 8+ | 通知组件index的位置有数据添加。 | -| onDataMove(from: number, to: number): void 8+ | 通知组件数据从from的位置移到to的位置。 | -| onDataDelete(index: number): void 8+ | 通知组件index的位置有数据删除。 | -| onDataChange(index: number): void 8+ | 通知组件index的位置有数据变化。 | - - -> **说明:** -> - 数据懒加载必须在容器组件内使用,且仅有List、Grid以及Swiper组件支持数据的懒加载(即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次加载所有的数据; -> -> - LazyForEach在每次迭代中,必须且只允许创建一个子组件; -> -> - 生成的子组件必须允许在LazyForEach的父容器组件中; -> -> - 允许LazyForEach包含在if/else条件渲染语句中,不允许LazyForEach中出现if/else条件渲染语句; -> -> - 为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,仅itemGenerator中的UI描述的组件内使用了状态变量时,才会触发组件刷新; -> -> - 子项生成器函数的调用顺序不一定和数据源中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作: -> ```ts -> LazyForEach(dataSource, item => {Text(`${++counter}. item.label`)}) -> ``` -> -> 正确的示例如下: -> -> ```ts -> LazyForEach(dataSource, -> item => Text(`${item.i}. item.data.label`)), -> item => item.data.id.toString()) -> ``` - - -## 示例 - -```ts -// Basic implementation of IDataSource to handle data listener -class BasicDataSource implements IDataSource { - private listeners: DataChangeListener[] = [] - - public totalCount(): number { - return 0 - } - public getData(index: number): any { - return undefined - } - - registerDataChangeListener(listener: DataChangeListener): void { - if (this.listeners.indexOf(listener) < 0) { - console.info('add listener') - this.listeners.push(listener) - } - } - unregisterDataChangeListener(listener: DataChangeListener): void { - const pos = this.listeners.indexOf(listener); - if (pos >= 0) { - console.info('remove listener') - this.listeners.splice(pos, 1) - } - } - - notifyDataReload(): void { - this.listeners.forEach(listener => { - listener.onDataReloaded() - }) - } - notifyDataAdd(index: number): void { - this.listeners.forEach(listener => { - listener.onDataAdd(index) - }) - } - notifyDataChange(index: number): void { - this.listeners.forEach(listener => { - listener.onDataChange(index) - }) - } - notifyDataDelete(index: number): void { - this.listeners.forEach(listener => { - listener.onDataDelete(index) - }) - } - notifyDataMove(from: number, to: number): void { - this.listeners.forEach(listener => { - listener.onDataMove(from, to) - }) - } -} - -class MyDataSource extends BasicDataSource { - private dataArray: string[] = ['/path/image0', '/path/image1', '/path/image2', '/path/image3'] - - public totalCount(): number { - return this.dataArray.length - } - public getData(index: number): any { - return this.dataArray[index] - } - - public addData(index: number, data: string): void { - this.dataArray.splice(index, 0, data) - this.notifyDataAdd(index) - } - public pushData(data: string): void { - this.dataArray.push(data) - this.notifyDataAdd(this.dataArray.length - 1) - } -} - -@Entry -@Component -struct MyComponent { - private data: MyDataSource = new MyDataSource() - build() { - List({space: 3}) { - LazyForEach(this.data, (item: string) => { - ListItem() { - Row() { - Image(item).width("30%").height(50) - Text(item).fontSize(20).margin({left:10}) - }.margin({left: 10, right: 10}) - } - .onClick(()=>{ - this.data.pushData('/path/image' + this.data.totalCount()) - }) - }, item => item) - } - } -} -``` diff --git a/zh-cn/application-dev/ui/ts-syntactic-sugar.md b/zh-cn/application-dev/ui/ts-syntactic-sugar.md deleted file mode 100644 index e7369cb4adc46939d4597cb8a62cd2fa60c5c442..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-syntactic-sugar.md +++ /dev/null @@ -1,197 +0,0 @@ -# 语法糖 - -## 装饰器 - - -装饰器@Decorator不仅可以装饰类或结构体,还可以装饰类的属性。多个装饰器可以叠加到目标元素,定义在同一行上或者在多行上,推荐定义在多行上。 - - -如下示例为@Component和@State的使用,被 @Component装饰的元素具备了组件化的含义,使用@State装饰的变量具备了状态数据的含义。 - - -```ts -@Component -struct MyComponent { - @State count: number = 0 -} -``` - - -装饰器定义在同一行上的描述如下: - - -```ts -@Entry @Component struct MyComponent { -} -``` - - -但更推荐定义在多行上: - - -```ts -@Entry -@Component -struct MyComponent { -} -``` - - -### 支持的装饰器列表 - -| 装饰器 | 装饰内容 | 说明 | -| ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -| @Component | struct | 结构体在装饰后具有基于组件的能力,需要实现build方法来更新UI。 | -| @Entry | struct | 组件被装饰后作为页面的入口,页面加载时将被渲染显示。 | -| @Preview | struct | 用@Preview装饰的自定义组件可以在DevEco Studio的预览器上进行预览,加载页面时,将创建并呈现@Preview装饰的自定义组件。 | -| @Builder | 方法 | 在@Builder装饰的方法里,通过声明式UI描述,可以在一个自定义组件内快速生成多个布局内容。 | -| @Extend | 方法 | @Extend装饰器将新的属性函数添加到内置组件上,通过@Extend装饰器可以快速定义并复用组件的自定义样式。 | -| @CustomDialog | struct | @CustomDialog装饰器用于装饰自定义弹窗。 | -| @State | 基本数据类型,类,数组 | 修饰的状态数据被修改时会触发组件的build方法进行UI界面更新。 | -| @Prop | 基本数据类型 | 修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,更新当前组件的UI。 | -| @Link | 基本数据类型,类,数组 | 父子组件之间的双向数据绑定,父组件的内部状态数据作为数据源,任何一方所做的修改都会反映给另一方。 | -| @Observed | 类 | @Observed应用于类,表示该类中的数据变更被UI页面管理。 | -| @ObjectLink | 被@Observed所装饰类的对象 | 装饰的状态数据被修改时,在父组件或者其他兄弟组件内与它关联的状态数据所在的组件都会更新UI。 | -| @Consume | 基本数据类型,类,数组 | @Consume装饰的变量在感知到@Provide装饰的变量更新后,会触发当前自定义组件的重新渲染。 | -| @Provide | 基本数据类型,类,数组 | @Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。 | -| @Watch | 被@State, @Prop, @Link, @ObjectLink, 
@Provide, @Consume, @StorageProp, @StorageLink中任意一个装饰的变量 | @Watch用于监听状态变量的变化,应用可以注册回调方法。 | - - -## 链式调用 - -允许开发者以“.”链式调用的方式配置UI结构及其属性、事件等。 - -```ts -Column() { - Image('1.jpg') - .alt('error.jpg') - .width(100) - .height(100) -}.padding(10) -``` - - -## struct对象 - -组件可以基于struct实现,组件不能有继承关系,struct可以比class更加快速的创建和销毁。 - -```ts -@Component -struct MyComponent { - @State data: string = '' - - build() { - } -} -``` - - -## 在实例化过程中省略"new" - -对于struct的实例化,可以省略new。 - -```ts -// 定义 -@Component -struct MyComponent { - build() { - } -} - -// 使用 -Column() { - MyComponent() -} - -// 等价于 -new Column() { - new MyComponent() -} -``` - - -## TS语言在生成器函数中的使用限制 - -TS语言的使用在生成器函数中存在一定的限制: - -- 表达式仅允许在字符串(${expression})、if条件、ForEach的参数和组件的参数中使用; - -- 这些表达式中的任何一个都不能导致任何应用程序状态变量(@State、@Link、@Prop)的改变,否则会导致未定义和潜在不稳定的框架行为; - -- 生成器函数内部不能有局部变量。 - -上述限制都不适用于事件处理函数(例如onClick)的匿名函数实现。 - -非法示例: - -```ts -build() { - let a: number = 1 // invalid: variable declaration not allowed - Column() { - Text(`Hello ${this.myName.toUpperCase()}`) // ok. - ForEach(this.arr.reverse(), ..., ...) // invalid: Array.reverse modifies the @State array variable in place - } - buildSpecial() // invalid: no function calls - Text(this.calcTextValue()) // this function call is ok. -} -``` - - -## 变量双向绑定 - -$$支持变量双向绑定,支持简单变量、@State、@Link、@Prop等类型。 - -当前$$仅支持[bindPopup](../reference/arkui-ts/ts-universal-attributes-popup.md)属性的show参数和@State变量之间的渲染,以及Radio组件的checked属性和Refresh组件的refreshing参数。 - - -```ts -// xxx.ets -@Entry -@Component -struct bindPopup { - @State customPopup: boolean = false - build() { - Column() { - Button(){ - Text('Popup') - } - .onClick(()=>{ - this.customPopup = !this.customPopup - }) - .bindPopup( - $$this.customPopup, { - message: "showPopup" - } - ) - } - } -} -``` - -## 状态变量多种数据类型声明使用限制 - -@State、@Provide、 @Link和@Consume四种状态变量的多种数据类型只能同时由简单数据类型或引用数据类型其中一种构成。 - -示例: - -```ts -@Entry -@Component -struct Index { - //错误写法: @State message: string | Resource = 'Hello World' - @State message: string = 'Hello World' - - build() { - Row() { - Column() { - Text(`${ this.message }`) - .fontSize(50) - .fontWeight(FontWeight.Bold) - } - .width('100%') - } - .height('100%') - } -} -``` - diff --git a/zh-cn/application-dev/ui/ts-ui-state-mgmt-concepts.md b/zh-cn/application-dev/ui/ts-ui-state-mgmt-concepts.md deleted file mode 100644 index 4ae1fd27f0dae8477177bcab5eac2acb0dfa1646..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ts-ui-state-mgmt-concepts.md +++ /dev/null @@ -1,29 +0,0 @@ -# 基本概念 - -在声明式UI编程范式中,UI是应用程序状态的函数,开发人员通过修改当前应用程序状态来更新相应的UI界面。如下图所示,开发框架提供了多种应用程序状态管理的能力。 - - -![](figures/CoreSpec_figures_state-mgmt-overview.png) - - -## 状态变量装饰器 - -- @State:组件拥有的状态属性,当@State装饰的变量更改时,组件会重新渲染更新UI。 - -- @Link:组件依赖于其父组件拥有的某些状态属性,当任何一个组件中的数据更新时,另一个组件的状态都会更新,父子组件重新渲染。 - -- @Prop:原理类似@Link,但是子组件所做的更改不会同步到父组件上,属于单向传递。 -> **说明:** -> 状态变量名称不能使用id,如@Prop id:number 。 - - -## 应用程序状态数据 - -AppStorage是整个UI应用程序状态的中心“数据库”,UI框架会针对应用程序创建单例AppStorage对象,并提供相应的装饰器和接口供应用程序使用。 - -- @StorageLink:@StorageLink(name)的原理类似于@Consume(name),不同的是,该给定名称的链接对象是从AppStorage中获得的,在UI组件和AppStorage之间建立双向绑定同步数据。 - -- @StorageProp:@StorageProp(name)将UI组件属性与AppStorage进行单向同步,AppStorage中值的更改会更新组件中的属性,但UI组件无法更改AppStorage中的属性值。 - -- AppStorage还提供用于业务逻辑实现的API,用于添加、读取、修改和删除应用程序的状态属性,此API所做的更改会导致修改的状态数据同步到UI组件上进行UI更新。 - diff --git a/zh-cn/application-dev/ui/ui-ts-building-data-model.md b/zh-cn/application-dev/ui/ui-ts-building-data-model.md index fe8843dd0050a63c369cfb2b4bb92c518b28e9a7..b0627fe491d6207825bf775dcc9a95d1c50c9d12 100644 --- a/zh-cn/application-dev/ui/ui-ts-building-data-model.md +++ b/zh-cn/application-dev/ui/ui-ts-building-data-model.md @@ -11,7 +11,7 @@ ![zh-cn_image_0000001195119619](figures/zh-cn_image_0000001195119619.png) 2. 定义食物数据的存储模型FoodData和枚举变量Category,FoodData类包含食物id、名称(name)、分类(category)、图片(image)、热量(calories)、蛋白质(protein)、脂肪(fat)、碳水(carbohydrates)和维生素C(vitaminC)属性。 - eTS语言是在ts语言的基础上的扩展,同样支持ts语法。 + ArkTS语言是在ts语言的基础上的扩展,同样支持ts语法。 ``` enum Category { @@ -87,4 +87,4 @@ ## 相关实例 针对构建食物分类列表页面和食物详情页,有以下相关实例可供参考: -- [DefiningPageLayoutAndConnection:页面布局和连接(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/DefiningPageLayoutAndConnection) +- [DefiningPageLayoutAndConnection:页面布局和连接(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/DefiningPageLayoutAndConnection) diff --git a/zh-cn/application-dev/ui/ui-ts-creating-simple-page.md b/zh-cn/application-dev/ui/ui-ts-creating-simple-page.md index a58772dcd84f01f7d4e52c8bd7a7a2e9430e4727..18152fe84e1c3ff337bd9db0b41ce9c3359adcfa 100644 --- a/zh-cn/application-dev/ui/ui-ts-creating-simple-page.md +++ b/zh-cn/application-dev/ui/ui-ts-creating-simple-page.md @@ -445,7 +445,7 @@ 5. 使用自定义构造函数\@Builder简化代码。可以发现,每个成分表中的成分单元其实都是一样的UI结构。 ![zh-cn_image_0000001169599582](figures/zh-cn_image_0000001169599582.png) - 当前对每个成分单元都进行了声明,造成了代码的重复和冗余。可以使用\@Builder来构建自定义方法,抽象出相同的UI结构声明。\@Builder修饰的方法和Component的build方法都是为了声明一些UI渲染结构,遵循一样的eTS语法。开发者可以定义一个或者多个\@Builder修饰的方法,但Component的build方法必须只有一个。 + 当前对每个成分单元都进行了声明,造成了代码的重复和冗余。可以使用\@Builder来构建自定义方法,抽象出相同的UI结构声明。\@Builder修饰的方法和Component的build方法都是为了声明一些UI渲染结构,遵循一样的ArkTS语法。开发者可以定义一个或者多个\@Builder修饰的方法,但Component的build方法必须只有一个。 在ContentTable内声明\@Builder修饰的IngredientItem方法,用于声明分类名、成分名称和成分含量UI描述。 @@ -551,6 +551,6 @@ 针对创建简单视图,有以下示例工程可供参考: -- [`BuildCommonView`:创建简单视图(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BuildCommonView) +- [`BuildCommonView`:创建简单视图(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BuildCommonView) 本示例为构建了简单页面展示食物番茄的图片和营养信息,主要为了展示简单页面的Stack布局和Flex布局。 diff --git a/zh-cn/application-dev/ui/ui-ts-layout-flex.md b/zh-cn/application-dev/ui/ui-ts-layout-flex.md index 2fe5474f2ac9a6ebee04cb63cb4ebe0311112758..16479a4c171c4459bebb61ca67e9ca9058a80c19 100644 --- a/zh-cn/application-dev/ui/ui-ts-layout-flex.md +++ b/zh-cn/application-dev/ui/ui-ts-layout-flex.md @@ -374,6 +374,6 @@ struct FlexExample { 针对弹性布局开发,有以下相关实例可供参考: -- [弹性布局(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/FlowLayoutEts) +- [弹性布局(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/FlowLayoutEts) -- [ArkUI常用布局容器对齐方式(eTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/LayoutAlignmentDemo) +- [ArkUI常用布局容器对齐方式(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/LayoutAlignmentDemo) diff --git a/zh-cn/application-dev/ui/ui-ts-layout-mediaquery.md b/zh-cn/application-dev/ui/ui-ts-layout-mediaquery.md index f0a4711db18bb4045ff214830373bd939a628630..b4402db80a9ae9c288ba74652aa61a6206c2c986 100644 --- a/zh-cn/application-dev/ui/ui-ts-layout-mediaquery.md +++ b/zh-cn/application-dev/ui/ui-ts-layout-mediaquery.md @@ -154,5 +154,5 @@ listener.on('change', onPortrait) 针对媒体查询开发,有以下相关实例可供参考: -- [`MediaQuery`:媒体查询(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/MediaQuery) +- [`MediaQuery`:媒体查询(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/MediaQuery) diff --git a/zh-cn/application-dev/ui/ui-ts-local-storage.md b/zh-cn/application-dev/ui/ui-ts-local-storage.md deleted file mode 100644 index 5330f574b0540c5613138558319e46fa155771d0..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/ui/ui-ts-local-storage.md +++ /dev/null @@ -1,359 +0,0 @@ -# Ability数据存储 - -> **说明:** 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 - -LocalStorage是应用程序中的存储单元,生命周期跟随其关联的Ability。LocalStorage为应用程序范围内的可变状态属性和非可变状态属性提供存储,可变状态属性和非可变状态属性是构建应用程序UI的一部分,如一个Ability的UI。 - -应用层:一个应用程序可以创建多个LocalStorage实例,应用程序的每一个Ability对应一个LocalStorage实例。 - -Ability: 一个应用程序可以拥有多个Ability,一个Ability中的所有子组件最多可以分配一个LocalStorage实例。并且,Ability中的所有子组件都将继承对此LocalStorage实例存储对象的访问权。 - -一个组件最多可以访问一个LocalStorage实例,一个LocalStorage对象可以分配给多个组件。 - -## @LocalStorageLink装饰器 - -组件通过使用@LocalStorageLink(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立双向数据绑定。当创建包含@LocalStorageLink的状态变量的组件时,该状态变量的值将会使用LocalStorage中的值进行初始化。如果LocalStorage中未定义初始值,将使用@LocalStorageLink定义的初始值。在UI组件中对@LocalStorageLink的状态变量所做的更改将同步到LocalStorage中,并从LocalStorage同步到Ability下的组件中。 - -## @LocalStorageProp装饰器 - -组件通过使用LocalStorageProp(key)装饰的状态变量,key值为LocalStorage中的属性键值,与LocalStorage建立单向数据绑定。当创建包含@LocalStorageProp的状态变量的组件时,该状态变量的值将使用LocalStorage中的值进行初始化。LocalStorage中的属性值的更改会导致当前Ability下的所有UI组件进行状态更新。 - -> **说明:** 创建LocalStorage实例时如未定义初始值,可以使用组件内@LocalStorageLink和@LocalStorageProp的初始值。如果定义时给定了初始值,那么不会再使用@LocalStorageLink和@LocalStorageProp的初始值。 - -## LocalStorage - -### constructor - -constructor(initializingProperties?: Object) - -创建一个新的LocalStorage对象,并进行初始化。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| ---------------------- | ------ | :--: | ---- | ---------------------------------------- | -| initializingProperties | Object | 否 | - | object.keys(obj)返回的所有对象属性及其值都将添加到LocalStorage。 | - - - -### GetShared - -static GetShared(): LocalStorage - -获取当前的共享的LocalStorage对象。 - -此接口仅可在Stage模型下使用。 - -**返回值:** - -| 类型 | 描述 | -| ----------------------------- | ----------------- | -| [LocalStorage](#localstorage) | 返回LocalStorage对象。 | - - - -### has - -has(propName: string): boolean - -判断属性值是否存在。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ------- | -| propName | string | 是 | - | 属性的属性值。 | - -**返回值:** - -| 类型 | 描述 | -| ------- | ------------- | -| boolean | 返回属性的属性值是否存在。 | - - - -### get - -get\(propName: string): T - -获取对应key值的value。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ----------- | -| propName | string | 是 | - | 要获取对应的key值。 | - -**返回值:** - -| 类型 | 描述 | -| -------------- | ---------------------------------------- | -| T \| undefined | 当keyvalue存在时,返回keyvalue值。不存在返回undefined。 | - - - -### set - -set\(propName: string, newValue: T): boolean - -存储对象值。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ----------- | -| propName | string | 是 | - | 要设置的key值。 | -| newValue | T | 是 | - | 要设置的value值。 | - -**返回值:** - -| 类型 | 描述 | -| ------- | ----------------------------------- | -| boolean | 如果存在key值,设置value值并返回true,否则返回false。 | - - - -### setOrCreate - -setOrCreate\(propName: string, newValue: T): boolean - -创建或更新setOrCreate内部的值。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | -------------- | -| propName | string | 是 | - | 要更新或者创建的key值。 | -| newValue | T | 是 | - | 要更新或创建的value值。 | - -**返回值:** - -| 类型 | 描述 | -| ------- | ---------------------------------------- | -| boolean | 如果已存在与给定键名字相同的属性,更新其值且返回true。如果不存在具有给定名称的属性,在LocalStorage中创建具有给定默认值的新属性,默认值必须是T类型。不允许undefined 或 null 返回true。 | - - - -### link - -link\(propName: string): T - -与localStorage双向数据绑定。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ----------- | -| propName | string | 是 | - | 要双向绑定的属性名称。 | - -**返回值:** - -| 类型 | 描述 | -| ---- | ---------------------------------------- | -| T | 如果存在具有给定键的属性,返回到此属性的双向绑定,该双向绑定意味着变量或者组件对数据的更改将同步到LocalStorage,然后通过LocalStorage实例同步到任何变量或组件。如果不存在给定键的属性,返回undefined。 | - - - -### setAndLink - -setAndLink\(propName: string, defaultValue: T): T - -与link接口类似,双向数据绑定localStorage。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| ------------ | ------ | :--: | ---- | ----------- | -| propName | string | 是 | - | 要进行创建的key值。 | -| defaultValue | T | 是 | - | 要进行设置的默认值。 | - -**返回值:** - -| 类型 | 描述 | -| ------------------------------------ | ------------------------------------------------------------ | -| [@Link](ts-component-states-link.md) | 与Link接口类似,如果当前的key保存于LocalStorage,返回该key值对应的value值。如果该key值未被创建,则创建一个对应的defaultValue的Link返回。 | - - - -### prop - -prop\(propName: string): T - -单向属性绑定的一种。更新组件的状态。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ------------- | -| propName | string | 是 | - | 要单向数据绑定的key值。 | - -**返回值:** - -| 类型 | 描述 | -| ------------------------------------ | ---------------------------------------- | -| [@Prop](ts-component-states-prop.md) | 如果存在具有给定键的属性,返回此属性的单向数据绑定。该单向绑定意味着只能通过LocalStorage将属性的更改同步到变量或组件。该方法返回的变量为不可变变量,适用于可变和不可变的状态变量。如果此键的属性不存在则返回undefined。 | - - - -### setAndProp - -setAndProp\(propName: string, defaultValue: T): T - -与Prop接口类似,存在localStorage的单向数据绑定prop值。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| ------------ | ------ | :--: | ---- | --------------- | -| propName | string | 是 | - | 要保存的的键值对中的key值。 | -| defaultValue | T | 是 | - | 创建的默认值。 | - -**返回值:** - -| 类型 | 描述 | -| ------------------------------------ | ---------------------------------------- | -| [@Prop](ts-component-states-prop.md) | 如果当前的key保存与LocalStorage,返回该key值对应的value值。如果该key值未被创建,则创建一个对应的defaultValue的Prop返回。 | - - - -### delete - -delete(propName: string): boolean - -删除key指定的键值对。 - -**参数:** - -| 参数名 | 类型 | 必填 | 默认值 | 参数描述 | -| -------- | ------ | :--: | ---- | ------------ | -| propName | string | 是 | - | 要删除的属性的key值。 | - -**返回值:** - -| 类型 | 描述 | -| ------- | ---------------------------------------- | -| boolean | 删除key指定的键值对,如果存在且删除成功返回true,不存在或删除失败返回false。 | - - - -### keys - -keys(): IterableIterator\ - -查找所有键。 - -**返回值:** - -| 类型 | 描述 | -| -------------- | -------------- | -| array\ | 返回包含所有键的字符串数组。 | - - - -### size - -size(): number - -存在的键值对的个数。 - -**返回值:** - -| 类型 | 描述 | -| ------ | --------- | -| number | 返回键值对的数量。 | - - - -### Clear - -clear(): boolean - -删除所有的属性。 - -**返回值:** - -| 类型 | 描述 | -| ------- | --------------------------------- | -| boolean | 删除所有的属性,如果当前有状态变量依旧引用此属性,返回false。 | - -### 示例1(在一个Ability创建的LocalStorage) - -LocalStorage通过loadContent接口加载,接口详见[loadContent](../reference/apis/js-apis-window.md#loadcontent9-1)。 - -```ts -import Ability from '@ohos.application.Ability' -export default class MainAbility extends Ability { - storage : LocalStorage - onCreate() { - this.storage = new LocalStorage(); - this.storage.setOrCreate("storageSimpleProp",121); - console.log("[Demo MainAbility onCreate]"); - } - onDestroy() { - console.log("[Demo MainAbility onDestroy]") - } - onWindowStageCreate(windowStage) { - // storage作为参数传递给loadContent接口。 - windowStage.loadContent("pages/index",this.storage) - } - onWindowStageDestroy() { - console.log("[Demo] MainAbility onWindoeStageDestroy") - } - onForeground() { - console.log("[Demo] MainAbility onForeground") - } - onBackground() { - console.log("[Demo] MainAbility onBackground") - } -} -``` - -@Component组件获取数据 - -```ts -let storage = LocalStorage.GetShared() -@Entry(storage) -@Component -struct LocalStorageComponent { - @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0 - build() { - Column(){ - Text(this.simpleVarName.toString()) - .onClick(()=>{ - this.simpleVarName +=1; - }) - Text(JSON.stringify(this.simpleVarName)) - .fontSize(50) - } - .height(500) - } -} -``` - -### 示例2(在Entry页面定义LocalStorage) - -```ts -let storage = new LocalStorage({"PropA":47}); -@Entry(storage) -@Component -struct ComA { - @LocalStorageLink("PropA") storLink: number = 1; - build() { - Column() { - Text(`Parent from LocalStorage ${ this.storLink }`) - .onClick(()=>this.storLink+=1) - Child() - } - } -} - - -@Component -struct Child{ - @LocalStorageLink("PropA") storLink: number = 1; - build() { - Text(`Parent from LocalStorage ${ this.storLink }`) - .onClick(()=>this.storLink+=1) - } -} -``` \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ui-ts-overview.md b/zh-cn/application-dev/ui/ui-ts-overview.md index e14132c51fc147d8f1844070ae9887de52986b6b..348ce1cde17b33f3a6bb7fe393e74427f6852a63 100644 --- a/zh-cn/application-dev/ui/ui-ts-overview.md +++ b/zh-cn/application-dev/ui/ui-ts-overview.md @@ -1,13 +1,13 @@ # 概述 -基于eTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。 +基于ArkTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。 ## 基础能力 -使用基于eTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。 +使用基于ArkTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。 -请参考[基于eTS的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解组件,更好地开发应用。 +请参考[基于ArkTS的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解组件,更好地开发应用。 - **开箱即用的组件** @@ -22,12 +22,12 @@ - **状态与数据管理** - 状态数据管理作为基于eTS的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。 + 状态数据管理作为基于ArkTS的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。 - **系统能力接口** - 使用基于eTS的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。 + 使用基于ArkTS的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。 ## 整体架构 @@ -59,54 +59,54 @@ ## 相关实例 -基于eTS的声明式开发范式的方舟开发框架,有以下相关实例可供参考: +基于ArkTS的声明式开发范式的方舟开发框架,有以下相关实例可供参考: -- [`Canvas`:画布组件(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Canvas) +- [`Canvas`:画布组件(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Canvas) -- [`Drag`:拖拽事件(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Drag) +- [`Drag`:拖拽事件(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Drag) -- [`ArkUIAnimation`:动画(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/ArkUIAnimation) +- [`ArkUIAnimation`:动画(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/ArkUIAnimation) -- [`Xcomponent`:XComponent(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/XComponent) +- [`Xcomponent`:XComponent(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/XComponent) -- [`MouseEvent`:鼠标事件(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/MouseEvent) +- [`MouseEvent`:鼠标事件(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/MouseEvent) -- [`Gallery`:组件集合(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Gallery) +- [`Gallery`:组件集合(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Gallery) -- [`BringApp`:拉起系统应用(eTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BringApp) +- [`BringApp`:拉起系统应用(ArkTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BringApp) -- [`Chat`:聊天示例应用(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/AppSample/Chat) +- [`Chat`:聊天示例应用(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/AppSample/Chat) -- [`Shopping`:购物示例应用(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/AppSample/Shopping) +- [`Shopping`:购物示例应用(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/AppSample/Shopping) -- [`Lottie`:Lottie(eTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Lottie) +- [`Lottie`:Lottie(ArkTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Lottie) -- [`Clock`:简单时钟(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/Preset/Clock) +- [`Clock`:简单时钟(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/Preset/Clock) -- [`Flybird`:小鸟避障游戏(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ResourcesSchedule/Flybird) +- [`Flybird`:小鸟避障游戏(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ResourcesSchedule/Flybird) -- [`AdaptiveCapabilities`:多设备自适应能力(eTS)(API9)](https://gitee.com/openharmony/app_samples/tree/master/MultiDeviceAppDev/AdaptiveCapabilities) +- [`AdaptiveCapabilities`:多设备自适应能力(ArkTS)(API9)](https://gitee.com/openharmony/app_samples/tree/master/MultiDeviceAppDev/AdaptiveCapabilities) -- [`Game2048`:2048游戏(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Game2048) +- [`Game2048`:2048游戏(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Game2048) -- [`TransitionAnimation`:转场动画(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/TransitionAnimation) +- [`TransitionAnimation`:转场动画(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/TransitionAnimation) -- [`PatternLock`:图案密码锁组件(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/PatternLock) +- [`PatternLock`:图案密码锁组件(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/PatternLock) -- [`Search`:Search组件(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Search) +- [`Search`:Search组件(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Search) -- [`QRCode`:二维码(eTS)(API9)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/QRCode) +- [`QRCode`:二维码(ArkTS)(API9)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/QRCode) -- [极简声明式UI范式(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/SimpleGalleryEts) +- [极简声明式UI范式(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/SimpleGalleryEts) -- [购物应用(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/ShoppingEts) +- [购物应用(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/ShoppingEts) -- [转场动画的使用(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/TransitionAnimtaionEts) +- [转场动画的使用(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/TransitionAnimtaionEts) -- [基础组件Slider的使用(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/SliderApplicationEts) +- [基础组件Slider的使用(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/SliderApplicationEts) -- [弹窗(eTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/CustomDialogEts) +- [弹窗(ArkTS)(API8)](https://gitee.com/openharmony/codelabs/tree/master/ETSUI/CustomDialogEts) -- [`UpgradePopup`:自定义弹窗(eTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/UpgradePopup) +- [`UpgradePopup`:自定义弹窗(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/UpgradePopup) -- [CustomComponent:组件化(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/CustomComponent) \ No newline at end of file +- [CustomComponent:组件化(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/CustomComponent) \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ui-ts-page-redirection-data-transmission.md b/zh-cn/application-dev/ui/ui-ts-page-redirection-data-transmission.md index 4c55c3a16abd697931b08fe0eb6589cdabeb74f5..493f5f60fa0c53a26a34673afa4ee7d7d29f26c3 100644 --- a/zh-cn/application-dev/ui/ui-ts-page-redirection-data-transmission.md +++ b/zh-cn/application-dev/ui/ui-ts-page-redirection-data-transmission.md @@ -267,6 +267,6 @@ 针对页面布局与连接,有以下示例工程可供参考: -- [`DefiningPageLayoutAndConnection`:页面布局和连接(eTS)(API8)](https://gitee.com/openharmony/app_samples/tree/master/ETSUI/DefiningPageLayoutAndConnection) +- [`DefiningPageLayoutAndConnection`:页面布局和连接(ArkTS)(API8)](https://gitee.com/openharmony/app_samples/tree/master/ETSUI/DefiningPageLayoutAndConnection) 本示例构建了食物分类列表页面和食物详情页,向开发者展示了List布局、Grid布局以及页面路由的基本用法。