• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 声明式UI开发指导
2
3## 开发说明
4
5| 任务          | 简介                                       | 相关资源                                     |
6| ----------- | ---------------------------------------- | ---------------------------------------- |
7| 准备开发环境      | 了解声明式UI的工程结构。<br>了解资源分类与访问。              | [OpenHarmony工程介绍](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-project-overview-0000001218440650)<br>[资源分类与访问](../quick-start/resource-categories-and-access.md) |
8| 学习ArkTS语言   | ArkTS是OpenHarmony优选的主力应用开发语言,当前,ArkTS在TS基础上主要扩展了声明式UI能力。 | [学习ArkTS语言](../quick-start/arkts-get-started.md) |
9| 开发页面        | 根据页面的使用场景,选择合适的布局。<br>根据页面需要实现的内容,添加系统内置组件,并修改组件样式。<br>更新页面内容,丰富页面展现形式。 | [创建页面](#创建页面)<br>        &nbsp;&nbsp;[常见布局开发指导](ui-ts-layout-linear.md)<br>        &nbsp;&nbsp;[常见组件说明](ui-ts-components-intro.md)<br>[修改组件样式](#修改组件样式)<br>[更新页面内容](#更新页面内容) |
10| (可选)页面多样化   | 绘图和动画。                                   | [绘图组件](../reference/arkui-ts/ts-drawing-components-circle.md)<br>[画布组件](../reference/arkui-ts/ts-components-canvas-canvas.md)<br>[动画](../reference/arkui-ts/ts-animatorproperty.md) |
11| (可选)页面之间的跳转 | 使用页面路由实现多个页面之前的跳转。                       | [页面路由](../reference/apis/js-apis-router.md) |
12| (可选)性能提升    | 避免低性能代码对应用的性能造成负面影响。                     | [性能提升的推荐方法](ui-ts-performance-improvement-recommendation.md) |
13
14## 创建页面
15
16请先根据页面预期效果选择布局结构创建页面,并在页面中添加基础的系统内置组件。下述示例采用了[弹性布局(Flex)](ui-ts-layout-flex.md),对页面中的Text组件进行横纵向居中布局显示。
17
18   ```ts
19    // xxx.ets
20    @Entry
21    @Component
22    struct MyComponent {
23      build() {
24        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
25          Text('Hello')
26        }
27        .width('100%')
28        .height('100%')
29      }
30    }
31   ```
32
33## 修改组件样式
34
35在页面中添加系统内置组件时,若不设置属性方法,则会显示其默认样式。通过更改组件的属性样式或者组件支持的[通用属性](../reference/arkui-ts/ts-universal-attributes-size.md)样式,改变组件的UI显示。
36
371. 通过修改Text组件的构造参数,将Text组件的显示内容修改为“Tomato”。
382. 修改Text组件的fontSize属性更改组件的字体大小,将字体大小设置为26,通过fontWeight属性更改字体粗细,将其设置为500。
39
40   ```ts
41    // xxx.ets
42    @Entry
43    @Component
44    struct MyComponent {
45      build() {
46        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
47          Text('Tomato')
48            .fontSize(26)
49            .fontWeight(500)
50        }
51        .width('100%')
52        .height('100%')
53      }
54    }
55   ```
56
57   ![zh-cn_image_0000001168888224](figures/zh-cn_image_0000001168888224.png)
58
59## 更新页面内容
60
61在创建基本的页面之后,可根据组件的状态来更新页面内容。以下示例展示了简单的更新页面方法。
62
63> **说明:**
64>
65> 更新组件的状态之前,请先初始化组件的成员变量。自定义组件的成员变量可以通过[本地初始化](../quick-start/arkts-restrictions-and-extensions.md#自定义组件成员变量初始化的方式与约束)和[在构造组件时通过构造参数初始化](../quick-start/arkts-restrictions-and-extensions.md#自定义组件成员变量初始化的方式与约束)两种方式实现,具体允许哪种方式取决于该变量所使用的装饰器。
66
67**示例:**
68
69```ts
70// xxx.ets
71@Entry
72@Component
73struct ParentComp {
74  @State isCountDown: boolean = true
75
76  build() {
77    Column() {
78      Text(this.isCountDown ? 'Count Down' : 'Stopwatch').fontSize(20).margin(20)
79      if (this.isCountDown) {
80        // 图片资源放在media目录下
81        Image($r("app.media.countdown")).width(120).height(120)
82        TimerComponent({ counter: 10, changePerSec: -1, showInColor: Color.Red })
83      } else {
84        // 图片资源放在media目录下
85        Image($r("app.media.stopwatch")).width(120).height(120)
86        TimerComponent({ counter: 0, changePerSec: +1, showInColor: Color.Black })
87      }
88      Button(this.isCountDown ? 'Switch to Stopwatch' : 'Switch to Count Down')
89        .onClick(() => {
90          this.isCountDown = !this.isCountDown
91        })
92    }.width('100%')
93  }
94}
95
96// 自定义计时器/倒计时组件
97@Component
98struct TimerComponent {
99  @State counter: number = 0
100  private changePerSec: number = -1
101  private showInColor: Color = Color.Black
102  private timerId: number = -1
103
104  build() {
105    Text(`${this.counter}sec`)
106      .fontColor(this.showInColor)
107      .fontSize(20)
108      .margin(20)
109  }
110
111  aboutToAppear() {
112    this.timerId = setInterval(() => {
113      this.counter += this.changePerSec
114    }, 1000)
115  }
116
117  aboutToDisappear() {
118    if (this.timerId > 0) {
119      clearTimeout(this.timerId)
120      this.timerId = -1
121    }
122  }
123}
124```
125
126![component](figures/component.gif)
127
128**初始创建和渲染:**
129
1301. 创建父组件ParentComp;
131
1322. 本地初始化ParentComp的状态变量isCountDown;
133
1343. 执行ParentComp的build函数;
135
1364. 创建Column组件;
137   1. 创建Text组件,设置其文本展示内容,并将Text组件实例添加到Column中;
138   2. 判断if条件,创建true条件下的元素;
139       1. 创建Image组件,并设置其图片源地址;
140       2. 使用给定的构造函数创建TimerComponent;
141   3. 创建Button内置组件,设置相应的内容。
142
143**状态更新:**
144
145用户单击按钮时:
146
1471. ParentComp的isCountDown状态变量的值更改为false;
148
1492. 执行ParentComp的build函数;
150
1513. Column组件被重用并执行重新初始化;
152
1534. Column的子组件会重用内存中的对象,但会进行重新初始化;
154   1. Text组件会被重用,但使用新的文本内容进行重新初始化;
155   2. 判断if条件,使用false条件下的元素;
156       1. 原来true条件的组件不再使用,将这些组件销毁;
157       2. 创建false条件下的组件;
158   3. 重用Button组件,使用新的图片源地址。