Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
ba673c62
D
Docs
项目概览
OpenHarmony
/
Docs
1 年多 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
ba673c62
编写于
10月 20, 2022
作者:
O
openharmony_ci
提交者:
Gitee
10月 20, 2022
浏览文件
操作
浏览文件
下载
差异文件
!10887 指南整改优化1
Merge pull request !10887 from luoying_ace/ly1020
上级
36d22833
ec44a0e4
变更
12
展开全部
隐藏空白更改
内联
并排
Showing
12 changed file
with
860 addition
and
949 deletion
+860
-949
zh-cn/application-dev/quick-start/arkts-basic-ui-description.md
...application-dev/quick-start/arkts-basic-ui-description.md
+54
-46
zh-cn/application-dev/quick-start/arkts-dynamic-ui-elememt-building.md
...tion-dev/quick-start/arkts-dynamic-ui-elememt-building.md
+138
-110
zh-cn/application-dev/quick-start/arkts-get-started.md
zh-cn/application-dev/quick-start/arkts-get-started.md
+11
-11
zh-cn/application-dev/quick-start/arkts-rendering-control.md
zh-cn/application-dev/quick-start/arkts-rendering-control.md
+150
-142
zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md
...tion-dev/quick-start/arkts-restrictions-and-extensions.md
+26
-27
zh-cn/application-dev/quick-start/arkts-state-mgmt-application-level.md
...ion-dev/quick-start/arkts-state-mgmt-application-level.md
+132
-110
zh-cn/application-dev/quick-start/arkts-state-mgmt-concepts.md
.../application-dev/quick-start/arkts-state-mgmt-concepts.md
+9
-9
zh-cn/application-dev/quick-start/arkts-state-mgmt-page-level.md
...pplication-dev/quick-start/arkts-state-mgmt-page-level.md
+253
-221
zh-cn/application-dev/reference/arkui-ts/ts-state-management.md
...application-dev/reference/arkui-ts/ts-state-management.md
+85
-74
zh-cn/application-dev/ui/Readme-CN.md
zh-cn/application-dev/ui/Readme-CN.md
+1
-5
zh-cn/application-dev/ui/ts-framework-directory.md
zh-cn/application-dev/ui/ts-framework-directory.md
+1
-1
zh-cn/application-dev/ui/ui-ts-basic-components-button.md
zh-cn/application-dev/ui/ui-ts-basic-components-button.md
+0
-193
未找到文件。
zh-cn/application-dev/quick-start/arkts-basic-ui-description.md
浏览文件 @
ba673c62
...
...
@@ -4,9 +4,9 @@ ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结
## 基本概念
-
struct:组件可以基于struct实现,不能有继承关系,对于struct的实例化,可以省略new。
-
struct:
自定义
组件可以基于struct实现,不能有继承关系,对于struct的实例化,可以省略new。
-
装饰器:装饰器给被装饰的对象赋予某一种能力,其不仅可以装饰类或结构体,还可以装饰类的属性。多个装饰器可以叠加到目标元素
,定义在同一行上或者多行上,推荐定义在多行上
。
-
装饰器:装饰器给被装饰的对象赋予某一种能力,其不仅可以装饰类或结构体,还可以装饰类的属性。多个装饰器可以叠加到目标元素
上,定义在同一行中或者分开多行,推荐分开多行定义
。
```
ts
@
Entry
...
...
@@ -15,7 +15,7 @@ ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结
}
```
-
build函数:自定义组件必须定义build函数,并且
自定义组件
禁止自定义构造函数。build函数满足Builder构造器接口定义,用于定义组件的声明式UI描述。
-
build函数:自定义组件必须定义build函数,并且禁止自定义构造函数。build函数满足Builder构造器接口定义,用于定义组件的声明式UI描述。
```
ts
interface
Builder
{
...
...
@@ -23,21 +23,21 @@ ArkTS通过装饰器@Component和@Entry装饰struct关键字声明的数据结
}
```
-
@Component:装饰struct,结构体在装饰后具有基于组件的能力,需要实现build方法来
更新
UI。
-
@Component:装饰struct,结构体在装饰后具有基于组件的能力,需要实现build方法来
创建
UI。
-
@Entry: 装饰struct,组件被装饰后作为页面的入口,页面加载时将被渲染显示。
-
@Preview:装饰struct, 用@Preview装饰的自定义组件可以在DevEco Studio的预览器上进行实时预览,加载页面时,将创建并
呈现@Preview装饰的自定义组件。
-
@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
组件的属性方法、事件方法
等。
## UI描述规范
### 无参数构造配置
组件的接口定义
不包含必选构造参数,组件后面的“()”中不需要配置任何内容。例如,Divider组件不包含构造参数:
如果组件的接口定义中
不包含必选构造参数,组件后面的“()”中不需要配置任何内容。例如,Divider组件不包含构造参数:
```
ts
Column
()
{
...
...
@@ -49,27 +49,27 @@ Column() {
### 必选参数构造配置
如果组件的接口定义中包含必选构造参数,则在组件后面的“()”中必须配置参数,参数可以使用常量进行赋值。
如果组件的接口定义中包含必选构造参数,则在组件后面的“()”中必须配置
相应
参数,参数可以使用常量进行赋值。
例如:
-
Image组件的必选参数src:
```
ts
Image
(
'
http
://xyz/a
.jpg
'
)
Image
(
'
http
s://xyz/test
.jpg
'
)
```
-
Text组件的必选参数content:
```
ts
Text
(
'
123
'
)
Text
(
'
test
'
)
```
变量或表达式也可以用于参数赋值,其中表达式返回的结果类型必须满足参数类型要求
。例如,传递
变量或表达式来构造Image和Text组件的参数:
变量或表达式也可以用于参数赋值,其中表达式返回的结果类型必须满足参数类型要求
,变量的定义详见
[
页面级变量的状态管理
](
arkts-state-mgmt-page-level.md
)
与
[
应用级变量的状态管理
](
arkts-state-mgmt-application-level.md
)
。例如,设置
变量或表达式来构造Image和Text组件的参数:
```
ts
Image
(
this
.
imagePath
)
Image
(
'
http://
'
+
this
.
imageUrl
)
Image
(
'
http
s
://
'
+
this
.
imageUrl
)
Text
(
`count:
${
this
.
count
}
`
)
```
...
...
@@ -80,14 +80,14 @@ Text(`count: ${this.count}`)
-
配置Text组件的字体大小属性:
```
ts
Text
(
'
123
'
)
Text
(
'
test
'
)
.
fontSize
(
12
)
```
-
使用"."
操作
进行链式调用并同时配置组件的多个属性,如下所示:
-
使用"."
运算符
进行链式调用并同时配置组件的多个属性,如下所示:
```
ts
Image
(
'
a
.jpg
'
)
Image
(
'
test
.jpg
'
)
.
alt
(
'
error.jpg
'
)
.
width
(
100
)
.
height
(
100
)
...
...
@@ -98,12 +98,12 @@ Text(`count: ${this.count}`)
```
ts
Text
(
'
hello
'
)
.
fontSize
(
this
.
size
)
Image
(
'
a
.jpg
'
)
Image
(
'
test
.jpg
'
)
.
width
(
this
.
count
%
2
===
0
?
100
:
200
)
.
height
(
this
.
offset
+
100
)
```
-
对于系统内置组件,框架还为其属性预定义了一些
[
枚举类型
](
../reference/arkui-ts/ts-appendix-enums.md
)
供开发人员调用,枚举类型
必须满足参数类型要求,枚举值可以作为参数传递。
可以按以下方式配置Text组件的颜色和字体属性:
-
对于系统内置组件,框架还为其属性预定义了一些
[
枚举类型
](
../reference/arkui-ts/ts-appendix-enums.md
)
供开发人员调用,枚举类型
可以作为参数传递,且必须满足参数类型要求。例如,
可以按以下方式配置Text组件的颜色和字体属性:
```
ts
Text
(
'
hello
'
)
...
...
@@ -114,7 +114,7 @@ Text(`count: ${this.count}`)
### 事件配置
通过事件方法可以配置组件支持的事件。
通过事件方法可以配置组件支持的事件
,事件方法紧随组件,并用"."运算符连接
。
-
使用lambda表达式配置组件的事件方法:
...
...
@@ -138,18 +138,18 @@ Text(`count: ${this.count}`)
```
ts
myClickHandler
():
void
{
this
.
counter
+=
2
}
...
Button
(
'
add counter
'
)
.
onClick
(
this
.
myClickHandler
)
```
### 子组件配置
对于支持子组件配置的组件,例如容器组件,在"{ ... }"里为组件添加子组件的UI描述。Column、Row、Stack、
Button、Grid和List
组件都是容器组件。
对于支持子组件配置的组件,例如容器组件,在"{ ... }"里为组件添加子组件的UI描述。Column、Row、Stack、
Grid、List等
组件都是容器组件。
-
以下是简单的Column示例:
...
...
@@ -164,32 +164,40 @@ Text(`count: ${this.count}`)
}
```
-
可以嵌套多个子组件
:
-
容器组件之间也可以互相嵌套,实现相对复杂的多级嵌套效果
:
```
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
)
Row
()
{
Image
(
'
test1.jpg
'
)
.
width
(
100
)
.
height
(
100
)
Button
(
'
click +1
'
)
.
onClick
(()
=>
{
console
.
info
(
'
+1 clicked!
'
)
})
}
Divider
()
Row
()
{
Image
(
'
test2.jpg
'
)
.
width
(
100
)
.
height
(
100
)
Button
(
'
click +2
'
)
.
onClick
(()
=>
{
console
.
info
(
'
+2 clicked!
'
)
})
}
Divider
()
Row
()
{
Image
(
'
test3.jpg
'
)
.
width
(
100
)
.
height
(
100
)
Button
(
'
click +3
'
)
.
onClick
(()
=>
{
console
.
info
(
'
+3 clicked!
'
)
})
}
}
```
\ No newline at end of file
zh-cn/application-dev/quick-start/arkts-dynamic-ui-elememt-building.md
浏览文件 @
ba673c62
# 动态构建UI元素
前面章节介绍的是如何创建一个组件
内部UI结构固定的自定义组件,为了满足开发者自定义组件内部UI结构的需求,ArkTS同时提供了动态构建UI元素的能力。
[
基本UI描述
](
arkts-basic-ui-description.md
)
介绍的是如何创建一个
内部UI结构固定的自定义组件,为了满足开发者自定义组件内部UI结构的需求,ArkTS同时提供了动态构建UI元素的能力。
## @Builder
可通过@Builder装饰器进行描述,该装饰器可以修饰一个函数,此函数可以在build函数之外声明,并在build函数中或其他@Builder修饰的函数中使用,在一个自定义组件内快速生成多个布局内容。使用方式如下面示例所示。
可通过@Builder装饰器进行描述,该装饰器可以修饰一个函数,此函数可以在build函数之外声明,并在build函数中或其他@Builder修饰的函数中使用,从而实现在一个自定义组件内快速生成多个布局内容。使用方式如下面示例所示。
```
ts
// xxx.ets
@
Component
struct
CompB
{
@
State
CompValue
:
string
=
''
;
@
State
CompValue
:
string
=
''
aboutToAppear
()
{
console
.
info
(
'
CompB aboutToAppear.
'
)
;
console
.
info
(
'
CompB aboutToAppear.
'
)
}
aboutToDisappear
()
{
console
.
info
(
'
CompB aboutToDisappear.
'
)
;
console
.
info
(
'
CompB aboutToDisappear.
'
)
}
build
()
{
...
...
@@ -33,22 +30,24 @@ struct CompB {
@
Entry
@
Component
struct
CompA
{
size1
:
number
=
100
;
@
State
CompValue1
:
string
=
"
Hello,CompValue1
"
;
@
State
CompValue2
:
string
=
"
Hello,CompValue2
"
;
@
State
CompValue3
:
string
=
"
Hello,CompValue3
"
;
size1
:
number
=
100
@
State
CompValue1
:
string
=
"
Hello,CompValue1
"
@
State
CompValue2
:
string
=
"
Hello,CompValue2
"
@
State
CompValue3
:
string
=
"
Hello,CompValue3
"
// @Builder装饰的函数
内使用自定义组件
// @Builder装饰的函数
CompC内使用自定义组件CompB
@
Builder
CompC
(
value
:
string
)
{
CompB
({
CompValue
:
value
})
;
CompB
({
CompValue
:
value
})
}
@
Builder
SquareText
(
label
:
string
)
{
Text
(
label
)
.
fontSize
(
18
)
.
width
(
1
*
this
.
size1
)
.
height
(
1
*
this
.
size1
)
}
// @Builder装饰的函数RowOfSquareTexts内使用@Builder装饰的函数SquareText
@
Builder
RowOfSquareTexts
(
label1
:
string
,
label2
:
string
)
{
Row
()
{
this
.
SquareText
(
label1
)
...
...
@@ -63,7 +62,6 @@ struct CompA {
Row
()
{
this
.
SquareText
(
"
A
"
)
this
.
SquareText
(
"
B
"
)
// or as long as tsc is used
}
.
width
(
2
*
this
.
size1
)
.
height
(
1
*
this
.
size1
)
...
...
@@ -71,9 +69,9 @@ struct CompA {
this
.
RowOfSquareTexts
(
"
C
"
,
"
D
"
)
Column
()
{
// 使用三次@Builder装饰的自定义组件
this
.
CompC
(
this
.
CompValue1
)
;
this
.
CompC
(
this
.
CompValue2
)
;
this
.
CompC
(
this
.
CompValue3
)
;
this
.
CompC
(
this
.
CompValue1
)
this
.
CompC
(
this
.
CompValue2
)
this
.
CompC
(
this
.
CompValue3
)
}
.
width
(
2
*
this
.
size1
)
.
height
(
2
*
this
.
size1
)
...
...
@@ -85,32 +83,33 @@ struct CompA {
```
## @BuilderParam<sup>8+<sup>
@BuilderParam装饰器用于修饰自定义组件内函数类型的属性(例如:
`@BuilderParam
content: () => any;
`
),并且在初始化自定义组件时被@BuilderParam修饰的属性必须赋值。
@BuilderParam装饰器用于修饰自定义组件内函数类型的属性(例如:
`@BuilderParam
noParam: () => void
`
),并且在初始化自定义组件时被@BuilderParam修饰的属性必须赋值。
### 引入动机
当开发者创建自定义组件,
想对该组件添加特定功能时(如:仅对自定义组件添加一个点击跳转操作)。若直接在组件内嵌入事件方法,将会导致所有初始化该组件的地方均增加了该功能。为解决此问题,引入了@BuilderParam装饰器,此装饰器修饰的属性值可为@Builder修饰的方法,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的
的功能。
当开发者创建自定义组件,
并想对该组件添加特定功能时(例如在自定义组件中添加一个点击跳转操作)。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,引入了@BuilderParam装饰器,此装饰器修饰的属性值可为@Builder装饰的函数,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定
的功能。
### 参数初始化组件
通过参数初始化组件时,将@Builder装饰的
方法赋值给@BuilderParam修饰的属性,并在自定义组件内调用content属性值。对@BuilderParam修饰的属性进行赋值时不带参数(如:
`content: this.specificParam`
),则此属性的类型需定义成无返回值的函数(如:
`@BuilderParam content: () => void`
)。若带参数(如:
`callContent: this.specificParam1("111")`
),则此属性的类型需定义成any(如:
`@BuilderParam callContent: any;
`
)。
通过参数初始化组件时,将@Builder装饰的
函数赋值给@BuilderParam修饰的属性,并在自定义组件内调用该属性值。若@BuilderParam修饰的属性在进行赋值时不带参数(如:
`noParam: this.specificNoParam`
),则此属性的类型需定义为无返回值的函数(如:
`@BuilderParam noParam: () => void`
);若带参数(如:
`withParam: this.SpecificWithParam('WithParamA')`
),则此属性的类型需定义成any(如:
`@BuilderParam withParam: any
`
)。
```
ts
// xxx.ets
@
Component
struct
CustomContainer
{
header
:
string
=
""
;
@
BuilderParam
noParam
:
()
=>
void
;
@
BuilderParam
withParam
:
any
;
footer
:
string
=
""
;
header
:
string
=
''
@
BuilderParam
noParam
:
()
=>
void
@
BuilderParam
withParam
:
any
footer
:
string
=
''
build
()
{
Column
()
{
Text
(
this
.
header
)
.
fontSize
(
5
0
)
.
fontSize
(
3
0
)
this
.
noParam
()
this
.
withParam
()
Text
(
this
.
footer
)
.
fontSize
(
5
0
)
.
fontSize
(
3
0
)
}
}
}
...
...
@@ -120,22 +119,32 @@ struct CustomContainer {
struct
CustomContainerUser
{
@
Builder
specificNoParam
()
{
Column
()
{
Text
(
"
noParam
"
).
fontSize
(
5
0
)
Text
(
'
noParam
'
).
fontSize
(
3
0
)
}
}
@
Builder
SpecificWithParam
(
label
:
string
)
{
Column
()
{
Text
(
label
).
fontSize
(
5
0
)
Text
(
label
).
fontSize
(
3
0
)
}
}
build
()
{
Column
()
{
CustomContainer
({
header
:
"
Header
"
,
header
:
'
HeaderA
'
,
noParam
:
this
.
specificNoParam
,
withParam
:
this
.
SpecificWithParam
(
'
WithParamA
'
),
footer
:
'
FooterA
'
})
Divider
()
.
strokeWidth
(
3
)
.
margin
(
10
)
CustomContainer
({
header
:
'
HeaderB
'
,
noParam
:
this
.
specificNoParam
,
withParam
:
this
.
SpecificWithParam
(
"
WithParam
"
),
footer
:
"
Footer
"
,
withParam
:
this
.
SpecificWithParam
(
'
WithParamB
'
),
footer
:
'
FooterB
'
})
}
}
...
...
@@ -144,45 +153,50 @@ struct CustomContainerUser {
### 尾随闭包初始化组件
在自定义组件中使用@BuilderParam修饰的属性
接收尾随闭包(在初始化自定义组件时,组件名称紧跟一个大括号“{}”形成尾随闭包场景(
`CustomComponent(){}`
)。开发者可把尾随闭包看做一个容器,向其填充内容,如在闭包内增加组件(
`{Column(){Text("content")
}`
),闭包内语法规范与build函数一致。此场景下自定义组件内有且仅有一个使用@BuilderParam修饰的属性。
在自定义组件中使用@BuilderParam修饰的属性
时也可通过尾随闭包进行初始化(在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景(
`CustomContainer(){}`
)。开发者可把尾随闭包看做一个容器,向其中填充内容,如在闭包内增加组件(
`{Column(){...
}`
),闭包内语法规范与build函数一致。此场景下自定义组件内有且仅有一个使用@BuilderParam修饰的属性。
示例:在闭包内
增加Column组件并添加点击事件,在新增的Column组件内调用@Builder修饰的specificParam方法,点击Column组件后该改变自定义组件中header的属性值为“changeHeader”。并且在初始化自定义组件时会把尾随闭包的内容赋值给使用
@BuilderParam修饰的closer属性。
示例:在闭包内
添加Column组件并设置点击事件,在Column组件内调用@Builder修饰的specificParam函数,点击Column组件后将自定义组件CustomContainer中header的属性值由“header”改变为“changeHeader”。在初始化自定义组件CustomContainer时,尾随闭包的内容会被赋值给
@BuilderParam修饰的closer属性。
```
ts
// xxx.ets
@
Component
struct
CustomContainer
{
header
:
string
=
""
;
@
BuilderParam
closer
:
()
=>
void
;
header
:
string
=
''
@
BuilderParam
closer
:
()
=>
void
build
()
{
Column
()
{
Text
(
this
.
header
)
.
fontSize
(
5
0
)
.
fontSize
(
3
0
)
this
.
closer
()
}
}
}
@
Builder
function
specificParam
(
label1
:
string
,
label2
:
string
)
{
Column
()
{
Text
(
label1
)
.
fontSize
(
5
0
)
.
fontSize
(
3
0
)
Text
(
label2
)
.
fontSize
(
5
0
)
.
fontSize
(
3
0
)
}
}
@
Entry
@
Component
struct
CustomContainerUser
{
@
State
text
:
string
=
"
header
"
@
State
text
:
string
=
'
header
'
build
()
{
Column
()
{
CustomContainer
({
header
:
this
.
text
,
}){
Column
(){
specificParam
(
"
111
"
,
"
22
"
)
}.
onClick
(()
=>
{
this
.
text
=
"
changeHeader
"
})
{
Column
()
{
specificParam
(
'
testA
'
,
'
testB
'
)
}.
backgroundColor
(
Color
.
Yellow
)
.
onClick
(()
=>
{
this
.
text
=
'
changeHeader
'
})
}
}
...
...
@@ -192,34 +206,41 @@ struct CustomContainerUser {
## @Styles
ArkTS为了避免开发者对重复样式的设置,通过@Styles装饰器可以将多
条样式设置提炼成一个方法,直接在组件声明的位置使用。@Styles装饰器将新的属性函数添加到基本组件上,如Text、Column、Button等。当前@Styles仅支持通用属性。通过@Styles装饰器可以快速定义并复用组件的自定义样式
。
ArkTS为了避免开发者对重复样式的设置,通过@Styles装饰器可以将多
个样式设置提炼成一个方法,直接在组件声明时调用,通过@Styles装饰器可以快速定义并复用自定义样式。当前@Styles仅支持通用属性
。
@Styles可以定义在组件内或组件外,在组件外定义时需在方法
前添加function关键字,组件内定义时
不需要添加function关键字。
@Styles可以定义在组件内或组件外,在组件外定义时需在方法
名前面添加function关键字,组件内定义时则
不需要添加function关键字。
```
ts
// xxx.ets
@
Styles
function
globalFancy
()
{
.
backgroundColor
(
Color
.
Red
)
@
Styles
function
globalFancy
()
{
.
width
(
150
)
.
height
(
100
)
.
backgroundColor
(
Color
.
Pink
)
}
@
Entry
@
Component
struct
FancyUse
{
@
Styles
componentFancy
()
{
.
backgroundColor
(
Color
.
Blue
)
.
width
(
100
)
.
height
(
200
)
.
backgroundColor
(
Color
.
Yellow
)
}
build
()
{
Column
({
space
:
10
})
{
Text
(
"
Fancy
"
)
Text
(
'
FancyA
'
)
.
globalFancy
()
.
width
(
100
)
.
height
(
100
)
.
fontSize
(
30
)
Text
(
"
Fancy
"
)
Text
(
'
FancyB
'
)
.
globalFancy
()
.
fontSize
(
20
)
Text
(
'
FancyC
'
)
.
componentFancy
()
.
width
(
100
)
.
height
(
100
)
.
fontSize
(
30
)
Text
(
'
FancyD
'
)
.
componentFancy
()
.
fontSize
(
20
)
}
}
}
...
...
@@ -227,35 +248,37 @@ struct FancyUse {
@Styles还可以在
[
StateStyles
](
../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md
)
属性内部使用,在组件处于不同的状态时赋予相应的属性。
在StateStyles内可以直接调用组件外定义的
Styles,但需要通过this关键字调用组件内定义的Styles
。
在StateStyles内可以直接调用组件外定义的
@Styles方法,但需要通过this关键字调用组件内定义的@Styles方法
。
```
ts
// xxx.ets
@
Styles
function
globalFancy
()
{
.
width
(
100
)
.
height
(
100
)
@
Styles
function
globalFancy
()
{
.
width
(
120
)
.
height
(
120
)
.
backgroundColor
(
Color
.
Green
)
}
@
Entry
@
Component
struct
FancyUse
{
@
Styles
componentFancy
()
{
.
width
(
50
)
.
height
(
50
)
.
width
(
80
)
.
height
(
80
)
.
backgroundColor
(
Color
.
Red
)
}
build
()
{
Row
({
space
:
10
})
{
Button
()
{
Text
(
"
Fancy
"
)
}
.
stateStyles
({
normal
:
{
.
width
(
80
)
.
height
(
80
)
},
disabled
:
this
.
componentFancy
,
pressed
:
globalFancy
})
Button
(
'
Fancy
'
)
.
stateStyles
({
normal
:
{
.
width
(
100
)
.
height
(
100
)
.
backgroundColor
(
Color
.
Blue
)
},
disabled
:
this
.
componentFancy
,
pressed
:
globalFancy
})
}
}
}
...
...
@@ -263,14 +286,15 @@ struct FancyUse {
## @Extend
@Extend装饰器将新的属性
函数添加到内置组件上,如Text、Column、Button等。通过@Extend装饰器可以快速的扩展原生组件。@Extend装饰器不能用在自定义组件struct定义框
内。
@Extend装饰器将新的属性
方法添加到Text、Column、Button等内置组件上,通过@Extend装饰器可以快速地扩展原生组件。@Extend不能定义在自定义组件struct
内。
```
ts
// xxx.ets
@
Extend
(
Text
)
function
fancy
(
fontSize
:
number
)
{
@
Extend
(
Text
)
function
fancy
(
fontSize
:
number
)
{
.
fontColor
(
Color
.
Red
)
.
fontSize
(
fontSize
)
.
fontStyle
(
FontStyle
.
Italic
)
.
fontWeight
(
600
)
}
@
Entry
...
...
@@ -282,62 +306,66 @@ struct FancyUse {
.
fancy
(
16
)
Text
(
"
Fancy
"
)
.
fancy
(
24
)
Text
(
"
Fancy
"
)
.
fancy
(
32
)
}
}
}
```
> **说明:**
>
> - @Extend装饰器不能
用在自定义组件struct定义框
内。
> - @Extend装饰器内仅支持属性
函数语句
。
> - @Extend装饰器不能
定义在自定义组件struct
内。
> - @Extend装饰器内仅支持属性
方法设置
。
## @CustomDialog
@CustomDialog装饰器用于装饰自定义弹窗
,使得弹窗可以动态设置
样式。
@CustomDialog装饰器用于装饰自定义弹窗
组件,使得弹窗可以动态设置内容及
样式。
```
ts
//
custom-dialog-demo
.ets
//
xxx
.ets
@
CustomDialog
struct
DialogExample
{
controller
:
CustomDialogController
;
action
:
()
=>
void
;
build
()
{
Row
()
{
Button
(
"
Close CustomDialog
"
)
.
onClick
(()
=>
{
this
.
controller
.
close
();
this
.
action
();
})
}.
padding
(
20
)
}
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!
"
);
}
dialogController
:
CustomDialogController
=
new
CustomDialogController
({
builder
:
DialogExample
({
action
:
this
.
onAccept
}),
cancel
:
this
.
existApp
,
autoCancel
:
true
});
onAccept
()
{
console
.
info
(
'
onAccept
'
);
}
build
()
{
Column
()
{
Button
(
"
Click to open Dialog
"
)
.
onClick
(()
=>
{
this
.
dialogController
.
open
()
})
}
existApp
()
{
console
.
info
(
'
Cancel dialog!
'
);
}
build
()
{
Column
()
{
Button
(
'
Click to open Dialog
'
)
.
onClick
(()
=>
{
this
.
dialogController
.
open
()
})
}
}
}
```
...
...
zh-cn/application-dev/quick-start/arkts-get-started.md
浏览文件 @
ba673c62
...
...
@@ -4,27 +4,27 @@ ArkTS是OpenHarmony优选的主力应用开发语言。ArkTS基于TypeScript(
-
ArkTS继承了TS的所有特性。
-
当前,ArkTS在TS
基础上主要扩展了
[
声明式UI
](
arkts-basic-ui-description.md
)
能力,让开发者
以更简洁、更自然的方式开发高性能应用。
-
当前,ArkTS在TS
的基础上主要扩展了
[
声明式UI
](
arkts-basic-ui-description.md
)
能力,让开发者能够
以更简洁、更自然的方式开发高性能应用。
当前扩展的声明式UI包括如下特性。
当前扩展的声明式UI
能力
包括如下特性。
-
[
基本UI描述
](
arkts-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提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的
部分
内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。
-
[
基本UI描述
](
arkts-basic-ui-description.md
)
:ArkTS定义了各种装饰器、自定义组件、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提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的
UI
内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。
-
[
使用限制与扩展
](
arkts-restrictions-and-extensions.md
)
:ArkTS在使用过程中存在限制与约束,同时也扩展了双向绑定等能力。
-
未来,ArkTS会结合应用开发/运行的需求持续演进,逐步提供并行和并发能力增强、
类型系统
增强、分布式开发范式等更多特性。
-
未来,ArkTS会结合应用开发/运行的需求持续演进,逐步提供并行和并发能力增强、
系统类型
增强、分布式开发范式等更多特性。
下面我们以一个具体的示例来说明ArkTS的基本组成。如下图所示的代码示例,UI界面
会两段文本
和一个按钮,当开发者点击按钮时,文本内容会从'Hello World'变为 'Hello ArkUI'。
下面我们以一个具体的示例来说明ArkTS的基本组成。如下图所示的代码示例,UI界面
包含两段文本、一条分割线
和一个按钮,当开发者点击按钮时,文本内容会从'Hello World'变为 'Hello ArkUI'。
![
arkts-get-started
](
figures/arkts-get-started.png
)
这个示例中所包含的ArkTS声明式开发范式的基本组成说明如下:
-
装饰器: 用于装饰类、结构、方法以及变量,赋予其特殊的含义,如上述示例中@Entry、@Component和@State都是装饰器。 具体而言,@Component表示这是个自定义组件;@Entry则表示这是个入口组件;@State表示
组件中的状态变量,这个状态变换会引起UI变更
。
-
装饰器: 用于装饰类、结构、方法以及变量,赋予其特殊的含义,如上述示例中@Entry、@Component和@State都是装饰器。 具体而言,@Component表示这是个自定义组件;@Entry则表示这是个入口组件;@State表示
这是组件中的状态变量,这个变量变化会触发UI刷新
。
-
自定义组件:可复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Hello。
-
UI描述:声明式的方法来描述UI的结构,例如build()方法中的代码块。
-
内置组件:ArkTS中默认内置的基
本组件和布局组件,开发者可以直接调用,如
Column、Text、Divider、Button等。
-
内置组件:ArkTS中默认内置的基
础组件、容器组件、媒体组件、绘制组件、画布组件等各种组件,开发者可以直接调用,如示例中的
Column、Text、Divider、Button等。
-
属性方法:用于组件属性的配置,如fontSize()、width()、height()、color()等,可通过链式调用的方式设置多项属性。
-
事件方法:用于添加组件对事件的响应逻辑,
统一通过事件方法进行设置,如跟随在Button后面的onClick()
。
-
事件方法:用于添加组件对事件的响应逻辑,
如跟随在Button后面的onClick(),同样可以通过链式调用的方式设置多个事件响应逻辑
。
zh-cn/application-dev/quick-start/arkts-rendering-control.md
浏览文件 @
ba673c62
# 渲染控制
ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的
部分
内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。
ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的
UI
内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。
## 条件渲染
...
...
@@ -9,61 +9,61 @@ ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状
> **说明:**
>
> - if条件语句可以使用状态变量。
> - if
/else
条件语句可以使用状态变量。
>
> - 使用if可以使子组件的渲染依赖条件语句。
> - 使用if
/else
可以使子组件的渲染依赖条件语句。
>
> - 必须在容器组件内使用。
>
> - 某些容器组件限制子组件的类型或数量
。将if放置在这些组件内时,这些限制将应用于if和else语句内创建的组件。例如,Grid组件的子组件仅支持GridItem组件,在Grid组件内使用if时,则if条件语句内
仅允许使用GridItem组件。
> - 某些容器组件限制子组件的类型或数量
,将if/else用于这些组件内时,这些限制将同样应用于if/else语句内创建的组件。例如,Grid容器组件的子组件仅支持GridItem组件,在Grid内使用if/else时,则if/else语句内也
仅允许使用GridItem组件。
```
ts
Column
()
{
if
(
this
.
count
<
0
)
{
Text
(
'
count is negative
'
)
}
else
if
(
this
.
count
%
2
===
0
)
{
Divider
()
Text
(
'
even
'
)
}
else
{
Divider
()
Text
(
'
odd
'
)
}
if
(
this
.
count
<
0
)
{
Text
(
'
count is negative
'
).
fontSize
(
14
)
}
else
if
(
this
.
count
%
2
===
0
)
{
Text
(
'
count is even
'
).
fontSize
(
14
)
}
else
{
Text
(
'
count is odd
'
).
fontSize
(
14
)
}
}
```
## 循环渲染
通过循环渲染(ForEach
组件)来迭代数组,并为每个数组
项创建相应的组件,可减少代码复杂度。
通过循环渲染(ForEach
)从数组中获取数据,并为每个数据
项创建相应的组件,可减少代码复杂度。
```
ForEach(
arr: any[],
itemGenerator: (item: any, index?: number) => void,
keyGenerator?: (item: any, index?: number) => string
)
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中的所有节点都将重建。 |
| 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
必须在容器组件内使用。
>
> - 生成的子组件
允许在ForEach的父容器组件中,允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中;
> - 生成的子组件
应当是允许包含在ForEach父容器组件中的子组件。
>
> -
子项生成器函数的调用顺序不一定和数组中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作:
> -
允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中。
>
> ```
> - itemGenerator函数的调用顺序不一定和数组中的数据项相同,在开发过程中不要假设itemGenerator和keyGenerator函数是否执行及其执行顺序。例如,以下示例可能无法正常工作:
>
> ```ts
> ForEach(anArray.map((item1, index1) => { return { i: index1 + 1, data: item1 }; }),
>
item => Text(`${item.i}. item.data.label`),
>
item => item.data.id.toString())
> item => Text(`${item.i}. item.data.label`),
> item => item.data.id.toString())
> ```
## 示例
...
...
@@ -76,20 +76,16 @@ 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
()
)
Column
({
space
:
5
})
{
Button
(
'
Reverse Array
'
)
.
onClick
(()
=>
{
this
.
arr
.
reverse
()
})
ForEach
(
this
.
arr
,
(
item
:
number
)
=>
{
Text
(
`item value:
${
item
}
`
).
fontSize
(
18
)
Divider
().
strokeWidth
(
2
)
},
(
item
:
number
)
=>
item
.
toString
())
}
}
}
...
...
@@ -97,28 +93,28 @@ struct MyComponent {
## 数据懒加载
通过数据懒加载(LazyForEach
组件
)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。
通过数据懒加载(LazyForEach)从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。
```
ts
LazyForEach
(
dataSource
:
IDataSource
,
itemGenerator
:
(
item
:
any
)
=>
void
,
keyGenerator
?:
(
item
:
any
)
=>
string
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
;
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
;
onDataReloaded
():
void
;
onDataAdd
(
index
:
number
):
void
;
onDataMove
(
from
:
number
,
to
:
number
):
void
;
onDataDelete
(
index
:
number
):
void
;
onDataChange
(
index
:
number
):
void
;
}
```
...
...
@@ -127,19 +123,19 @@ interface DataChangeListener {
| 参数名 | 参数类型 | 必填 | 参数描述 |
| ------------- | --------------------- | ---- | ------------------------------------------------------------ |
| dataSource | IDataSource | 是 | 实现IDataSource接口的对象,需要开发者实现相关接口。 |
| itemGenerator | (item: any) => void | 是 | 生成子组件的lambda函数,为
给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{.
...}”中。 |
| keyGenerator | (item: any) => string | 否 | 匿名函数,用于
键值生成,为给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子
项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 |
| itemGenerator | (item: any) => void | 是 | 生成子组件的lambda函数,为
数组中的每一个数据项创建一个或多个子组件,单个子组件或子组件列表必须包括在大括号“{
...}”中。 |
| keyGenerator | (item: any) => string | 否 | 匿名函数,用于
给数组中的每一个数据项生成唯一且固定的键值。当数据项在数组中的位置更改时,其键值不得更改,当数组中的数据
项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 |
表2
IDataSource类型说明
###
IDataSource类型说明
| 名称 | 描述 |
| ------------------------------------------------------------ | ---------------------- |
| totalCount(): number | 获取数据总数。 |
| getData(index: number): any | 获取索引对应的数据。 |
| registerDataChangeListener(listener:DataChangeListener): void | 注册
改变数据的控制
器。 |
| unregisterDataChangeListener(listener:DataChangeListener): void | 注销
改变数据的控制
器。 |
| getData(index: number): any | 获取索引
值index
对应的数据。 |
| registerDataChangeListener(listener:DataChangeListener): void | 注册
数据改变的监听
器。 |
| unregisterDataChangeListener(listener:DataChangeListener): void | 注销
数据改变的监听
器。 |
表3
DataChangeListener类型说明
###
DataChangeListener类型说明
| 名称 | 描述 |
| -------------------------------------------------------- | -------------------------------------- |
...
...
@@ -156,115 +152,127 @@ interface DataChangeListener {
## 示例
```
ts
// xxx.ets
class
BasicDataSource
implements
IDataSource
{
private
listeners
:
DataChangeListener
[]
=
[]
private
listeners
:
DataChangeListener
[]
=
[]
public
totalCount
():
number
{
return
0
}
public
getData
(
index
:
number
):
any
{
return
undefined
}
public
totalCount
():
number
{
return
0
}
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
)
}
}
public
getData
(
index
:
number
):
any
{
return
undefined
}
notifyDataReload
(
):
void
{
this
.
listeners
.
forEach
(
listener
=>
{
listener
.
onDataReloaded
(
)
}
)
registerDataChangeListener
(
listener
:
DataChangeListener
):
void
{
if
(
this
.
listeners
.
indexOf
(
listener
)
<
0
)
{
console
.
info
(
'
add listener
'
)
this
.
listeners
.
push
(
listener
)
}
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
)
})
}
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
'
]
// 初始化数据列表
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
totalCount
():
number
{
return
this
.
dataArray
.
length
}
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
)
}
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
)
private
data
:
MyDataSource
=
new
MyDataSource
()
build
()
{
List
({
space
:
3
})
{
LazyForEach
(
this
.
data
,
(
item
:
string
)
=>
{
ListItem
()
{
Row
()
{
Image
(
item
).
width
(
50
).
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必须在容器组件内使用,目前仅有List、Grid以及Swiper组件支持数据懒加载(即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据。
>
> - LazyForEach在每次迭代中,必须
且只允许创建一个子组件;
> - LazyForEach在每次迭代中,必须
创建且只允许创建一个子组件。
>
> - 生成的子组件必须
允许在LazyForEach的父容器组件中;
> - 生成的子组件必须
是允许包含在LazyForEach父容器组件中的子组件。
>
> - 允许LazyForEach包含在if/else条件渲染语句中,
不允许LazyForEach中出现if/else条件渲染语句;
> - 允许LazyForEach包含在if/else条件渲染语句中,
但不允许LazyForEach中出现if/else条件渲染语句。
>
> - 为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,仅
itemGenerator中的UI描述的组件内使用了状态变量时,才会触发组件刷新;
> - 为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,仅
当itemGenerator中创建的子组件内使用了状态变量时,才会触发组件刷新。
>
> -
子项生成器函数的调用顺序不一定和数据源中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如
下示例可能无法正常工作:
> -
itemGenerator函数的调用顺序不一定和数据源中的数据项相同,在开发过程中不要假设itemGenerator和keyGenerator函数是否执行及其执行顺序。例如,以
下示例可能无法正常工作:
>
> ```ts
> LazyForEach(dataSource,
>
item => Text(`${item.i}. item.data.label`)),
>
item => item.data.id.toString())
> item => Text(`${item.i}. item.data.label`)),
> item => item.data.id.toString())
> ```
\ No newline at end of file
zh-cn/application-dev/quick-start/arkts-restrictions-and-extensions.md
浏览文件 @
ba673c62
...
...
@@ -4,48 +4,47 @@
ArkTS语言的使用在生成器函数中存在一定的限制:
-
表达式仅允许在字符串(${expression})、if条件、ForEach的参数和组件的参数中使用;
-
任何表达式都不能导致任何应用程序状态变量(@State、@Link、@Prop)的改变,否则会导致未定义和潜在不稳定的框架行为;
-
表达式仅允许在字符串(${expression})、if/else条件语句、ForEach的参数以及组件的参数中使用。
-
任何表达式都不能导致应用程序中状态变量(@State、@Link、@Prop)的改变,否则会造成未定义和潜在不稳定的框架行为。
-
生成器函数内部不能有局部变量。
上述限制都不适用于事件
处理函数(例如onClick)的匿
函数实现。
上述限制都不适用于事件
方法(如onClick)的匿名
函数实现。
## 变量的双向绑定
ArkTS支持通过$$双向绑定变量,通常应用于状态值频繁改变的变量。
-
当前$$支持基础类型变量,以及@State、@Link和@Prop装饰的变量。
-
当前$$仅支持
[
bindPopup
](
../reference/arkui-ts/ts-universal-attributes-popup.md
)
属性
的show参数和@State变量之间的渲染,Radio组件的checked属性
。
-
$$绑定的变量变
更时,仅渲染
当前组件,提高渲染速度。
-
当前$$仅支持
[
bindPopup
](
../reference/arkui-ts/ts-universal-attributes-popup.md
)
属性
方法的show参数,
[
Radio
](
../reference/arkui-ts/ts-basic-components-radio.md
)
组件的checked属性,
[
Refresh
](
../reference/arkui-ts/ts-container-refresh.md
)
组件的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
,
{
mesage
:
"
showPopup
"
}
)
}
}
}
struct
bindPopupPage
{
@
State
customPopup
:
boolean
=
false
build
()
{
Column
()
{
Button
(
'
Popup
'
)
.
margin
(
20
)
.
onClick
(()
=>
{
this
.
customPopup
=
!
this
.
customPopup
})
.
bindPopup
(
$$this
.
customPopup
,
{
message
:
"
showPopup
"
})
}
}
}
```
## 状态变量
多种
数据类型声明使用限制
## 状态变量数据类型声明使用限制
@State、@Provide、 @Link和@Consume四种状态变量的
多种数据类型只能同时由简单数据类型或引用数据类型
其中一种构成。
@State、@Provide、 @Link和@Consume四种状态变量的
数据类型声明只能由简单数据类型或引用数据类型的
其中一种构成。
示例:
...
...
@@ -53,14 +52,14 @@ struct bindPopup {
// xxx.ets
@
Entry
@
Component
struct
Index
{
struct
Index
Page
{
//错误写法: @State message: string | Resource = 'Hello World'
@
State
message
:
string
=
'
Hello World
'
build
()
{
Row
()
{
Column
()
{
Text
(
`
${
this
.
message
}
`
)
Text
(
`
${
this
.
message
}
`
)
.
fontSize
(
50
)
.
fontWeight
(
FontWeight
.
Bold
)
}
...
...
zh-cn/application-dev/quick-start/arkts-state-mgmt-application-level.md
浏览文件 @
ba673c62
# 应用级变量的状态管理
在前面的章节中,已经讲述了如何管理页面级变量的状态,本章将说明如何管理应用级变量的状态,具体接口请参考
[
应用级变量的状态管理接口
](
../reference/arkui-ts/ts-state-management.md
)
。
在前面的章节中,已经讲述了如何管理页面级变量的状态,本章将说明如何管理应用级变量的状态,具体接口
说明
请参考
[
应用级变量的状态管理接口
](
../reference/arkui-ts/ts-state-management.md
)
。
##
AppStorage
##
[AppStorage](../reference/arkui-ts/ts-state-management.md#appstorage)
AppStorage是应用程序中的单例对象,由UI框架在应用程序启动时创建,在应用程序退出时销毁,为应用程序范围内的可变状态属性提供中央存储。
AppStorage包含整个应用程序中需要访问的所有状态属性,只要应用程序保持运行,AppStorage就会保存所有属性及属性值,属性值可以通过唯一的键值进行访问。
组件可以通过装饰器将应用程序状态数据与AppStorage进行同步,应用业务逻辑的实现也可以通过接口访问AppStorage。
AppStorage的选择状态属性可以与不同的数据源或数据接收器同步,这些数据源和接收器可以是设备上的本地或远程,并具有不同的功能,如数据持久性。这样的数据源和接收器可以独立于UI在业务逻辑中实现。
默认情况下,AppStorage中的属性是可变的,AppStorage还可使用不可变(只读)属性。
...
...
@@ -22,54 +20,59 @@ AppStorage的选择状态属性可以与不同的数据源或数据接收器同
### @StorageProp装饰器
组件通过使用@StorageProp(key)装饰的状态变量,
将与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StoageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中的属性值的更改会导致绑定
的UI组件进行状态更新。
组件通过使用@StorageProp(key)装饰的状态变量,
与AppStorage建立单向数据绑定,key标识AppStorage中的属性键值。当创建包含@StorageProp的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化。AppStorage中属性值的更改会导致绑定该状态变量
的UI组件进行状态更新。
### 示例
每次用户单击Count按钮时,this.varA变量值都会增加
,此变量与AppStorage中的varA同步。每次用户单击当前语言按钮时,修改AppStorage中的languageCode,此修改会同步给this.lang
变量。
每次用户单击Count按钮时,this.varA变量值都会增加
1,此变量与AppStorage中的varA同步。每次用户单击language按钮时,修改AppStorage中的languageCode,此修改会同步给this.languageCode
变量。
```
ts
// xxx.ets
@
Entry
@
Component
struct
ComponentA
{
@
StorageLink
(
'
varA
'
)
varA
:
number
=
2
@
StorageProp
(
'
languageCode
'
)
lang
:
string
=
'
en
'
@
StorageProp
(
'
languageCode
'
)
lang
uageCode
:
string
=
'
en
'
private
label
:
string
=
'
count
'
aboutToAppear
()
{
this
.
label
=
(
this
.
lang
===
'
zh
'
)
?
'
数
'
:
'
Count
'
this
.
label
=
(
this
.
lang
uageCode
===
'
zh
'
)
?
'
数量
'
:
'
Count
'
}
build
()
{
Column
(){
Column
()
{
Row
({
space
:
20
})
{
Button
(
`
${
this
.
label
}
:
${
this
.
varA
}
`
)
.
onClick
(()
=>
{
AppStorage
.
Set
<
number
>
(
'
varA
'
,
AppStorage
.
Get
<
number
>
(
'
varA
'
)
+
1
)
})
Button
(
`lang
:
${
this
.
lang
}
`
)
Button
(
`lang
uage:
${
this
.
languageCode
}
`
)
.
onClick
(()
=>
{
if
(
this
.
lang
===
'
zh
'
)
{
if
(
AppStorage
.
Get
<
string
>
(
'
languageCode
'
)
===
'
zh
'
)
{
AppStorage
.
Set
<
string
>
(
'
languageCode
'
,
'
en
'
)
}
else
{
AppStorage
.
Set
<
string
>
(
'
languageCode
'
,
'
zh
'
)
}
this
.
label
=
(
this
.
lang
===
'
zh
'
)
?
'
数
'
:
'
Count
'
this
.
label
=
(
this
.
lang
uageCode
===
'
zh
'
)
?
'
数量
'
:
'
Count
'
})
}
.
margin
({
bottom
:
50
})
Row
(){
Button
(
`更改@StorageLink修饰的变量:
${
this
.
varA
}
`
).
fontSize
(
10
)
Row
()
{
Button
(
`更改@StorageLink修饰的变量:
${
this
.
varA
}
`
).
height
(
40
).
fontSize
(
14
)
.
onClick
(()
=>
{
this
.
varA
++
})
}.
margin
({
bottom
:
50
})
Row
(){
Button
(
`更改@StorageProp修饰的变量:
${
this
.
lang
}
`
).
fontSize
(
10
)
Row
()
{
Button
(
`更改@StorageProp修饰的变量:
${
this
.
languageCode
}
`
).
height
(
40
).
fontSize
(
14
)
.
onClick
(()
=>
{
this
.
lang
=
'
test
'
if
(
this
.
languageCode
===
'
zh
'
)
{
this
.
languageCode
=
'
en
'
}
else
{
this
.
languageCode
=
'
zh
'
}
})
}
}
...
...
@@ -77,17 +80,18 @@ struct ComponentA {
}
```
!
[
appstorage
](
figures/appstorage.gif
)
##
LocalStorage
##
[LocalStorage](../reference/arkui-ts/ts-state-management.md#localstorage9)
> **说明:** 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
> **说明:**
>
> 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
LocalStorage是应用程序中的存储单元,生命周期跟随其关联的Ability。LocalStorage为应用程序范围内的可变状态属性和非可变状态属性提供存储,可变状态属性和非可变状态属性是构建应用程序UI的一部分,如一个Ability的UI。
应用层:一个应用程序可以创建多个LocalStorage实例,应用程序的每一个Ability对应一个LocalStorage实例。
Ability:
一个应用程序可以拥有多个Ability,一个Ability中的所有子组件最多可以分配一个LocalStorage实例。并且,Ability中的所有子组件都将继承对此LocalStorage实例存储对象的访问权。
Ability:一个应用程序可以拥有多个Ability,一个Ability中的所有子组件最多可以分配一个LocalStorage实例。并且,Ability中的所有子组件都将继承对此LocalStorage实例存储对象的访问权。
一个组件最多可以访问一个LocalStorage实例,一个LocalStorage对象可以分配给多个组件。
...
...
@@ -101,150 +105,168 @@ Ability: 一个应用程序可以拥有多个Ability,一个Ability中的所
> **说明:** 创建LocalStorage实例时如未定义初始值,可以使用组件内@LocalStorageLink和@LocalStorageProp的初始值。如果定义时给定了初始值,那么不会再使用@LocalStorageLink和@LocalStorageProp的初始值。
### 示例1(在一个Ability
创建的
LocalStorage)
### 示例1(在一个Ability
中创建
LocalStorage)
LocalStorage通过loadContent接口加载,接口详见
[
loadContent
](
../reference/apis/js-apis-window.md#loadcontent9-1
)
。
LocalStorage通过loadContent接口加载,接口
说明
详见
[
loadContent
](
../reference/apis/js-apis-window.md#loadcontent9-1
)
。
```
```
ts
// MainAbility.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")
}
export
default
class
MainAbility
extends
Ability
{
storage
:
LocalStorage
onCreate
()
{
this
.
storage
=
new
LocalStorage
()
this
.
storage
.
setOrCreate
(
'
storageSimpleProp
'
,
121
)
console
.
info
(
'
[Demo MainAbility onCreate]
'
)
}
onDestroy
()
{
console
.
info
(
'
[Demo MainAbility onDestroy]
'
)
}
onWindowStageCreate
(
windowStage
)
{
// storage作为参数传递给loadContent接口
windowStage
.
loadContent
(
'
pages/index
'
,
this
.
storage
)
}
onWindowStageDestroy
()
{
console
.
info
(
'
[Demo] MainAbility onWindowStageDestroy
'
)
}
onForeground
()
{
console
.
info
(
'
[Demo] MainAbility onForeground
'
)
}
onBackground
()
{
console
.
info
(
'
[Demo] MainAbility onBackground
'
)
}
}
```
@Component组件获取数据
```
```
ts
// index.ets
let
storage
=
LocalStorage
.
GetShared
()
@
Entry
(
storage
)
@
Component
struct
LocalStorageComponent
{
@LocalStorageLink("storageSimpleProp") simpleVarName: number = 0
@
LocalStorageLink
(
'
storageSimpleProp
'
)
simpleVarName
:
number
=
0
build
()
{
Column(){
Button(`LocalStorageLink: ${ this.simpleVarName.toString() }`)
.onClick(()=>{
this.simpleVarName +=1;
Column
()
{
Button
(
`LocalStorageLink:
${
this
.
simpleVarName
.
toString
()}
`
)
.
margin
(
20
)
.
onClick
(()
=>
{
this
.
simpleVarName
+=
1
})
Text
(
JSON
.
stringify
(
this
.
simpleVarName
))
.
fontSize
(
50
)
LocalStorageComponentProp();
}
.height(500)
LocalStorageComponentProp
()
}.
width
(
'
100%
'
)
}
}
@
Component
struct
LocalStorageComponentProp
{
@LocalStorageProp("storageSimpleProp") simpleVarName: number = 0
@
LocalStorageProp
(
'
storageSimpleProp
'
)
simpleVarName
:
number
=
0
build
()
{
Column
()
{
Button(`LocalStorageProp: ${ this.simpleVarName.toString() }`)
Button
(
`LocalStorageProp:
${
this
.
simpleVarName
.
toString
()}
`
)
.
margin
(
20
)
.
onClick
(()
=>
{
this.simpleVarName += 1
;
this
.
simpleVarName
+=
1
})
Text
(
JSON
.
stringify
(
this
.
simpleVarName
))
.
fontSize
(
50
)
}
.height(500)
}.
width
(
'
100%
'
)
}
}
```
### 示例2(在Entry页面定义LocalStorage)
```
let storage = new LocalStorage({"PropA":47});
```
ts
// xxx.ets
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
ComA
{
@
LocalStorageLink
(
"
PropA
"
)
storageLink
:
number
=
1
build
()
{
Column
()
{
Text
(
`Parent from LocalStorage
${
this
.
storageLink
}
`
)
.
fontSize
(
18
)
.
margin
(
20
)
.
onClick
(()
=>
this
.
storageLink
+=
1
)
Child
()
}
}
}
@
Component
struct Child{
@LocalStorageLink("PropA") storLink: number = 1;
build() {
Text(`Parent from LocalStorage ${ this.storLink }`)
.onClick(()=>this.storLink+=1)
struct
Child
{
@
LocalStorageLink
(
"
PropA
"
)
storageLink
:
number
=
1
build
()
{
Text
(
`Child from LocalStorage
${
this
.
storageLink
}
`
)
.
fontSize
(
18
)
.
margin
(
20
)
.
onClick
(()
=>
this
.
storageLink
+=
1
)
}
}
```
##
PersistentStorage
##
[PersistentStorage](../reference/arkui-ts/ts-state-management.md#persistentstorage)
PersistentStorage
类
提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。
PersistentStorage提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。
> **说明:**
>
> - Persist
Prop接口使用时,需要保证输入对应的key应当在AppStorage
存在。
> -
DeleteProp接口使用时,只能对本次启动
已经link过的数据生效。
> - Persist
entStorage的PersistProp接口使用时,需要保证输入对应的key在AppStorage中
存在。
> -
PersistentStorage的DeleteProp接口使用时,只能对本次应用启动时
已经link过的数据生效。
```
ts
// xxx.ets
PersistentStorage
.
PersistProp
(
"
highScore
"
,
"
0
"
);
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
(
1
0
)
}
.
onClick
(()
=>
{
this
.
currentScore
++
if
(
this
.
currentScore
>
Number
(
this
.
highScore
))
{
this
.
highScore
=
this
.
currentScore
.
toString
()
}
})
}
}
@
StorageLink
(
'
highScore
'
)
highScore
:
string
=
'
0
'
@
State
currentScore
:
number
=
0
build
()
{
Column
(
)
{
if
(
this
.
currentScore
===
Number
(
this
.
highScore
))
{
Text
(
`new highScore :
${
this
.
highScore
}
`
).
fontSize
(
18
)
}
Button
(
`goal!, currentScore :
${
this
.
currentScore
}
`
)
.
margin
(
2
0
)
.
onClick
(()
=>
{
this
.
currentScore
++
if
(
this
.
currentScore
>
Number
(
this
.
highScore
))
{
this
.
highScore
=
this
.
currentScore
.
toString
()
}
})
}.
width
(
'
100%
'
)
}
}
```
!
[
PersistentStorage
](
figures/PersistentStorage.gif
)
## [Environment](../reference/arkui-ts/ts-state-management.md#environment)
## Environment
Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态数据,这些数据描述了应用程序运行的设备环境,包括系统语言、深浅色模式等等。Environment及其属性是不可变的,所有数据类型均为简单类型。如下示例展示了从Environment获取系统是否开启无障碍屏幕朗读:
Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态属性,这些属性描述了应用程序运行的设备环境。Environment及其属性是不可变的,所有属性值类型均为简单类型。如下示例展示了从Environment获取语音环境:
```
Environment.EnvProp("accessibilityEnabled", "default");
var enable = AppStorage.Get("accessibilityEnabled");
```
ts
Environment
.
EnvProp
(
'
accessibilityEnabled
'
,
'
default
'
)
var
enable
=
AppStorage
.
Get
(
'
accessibilityEnabled
'
)
```
accessibilityEnabled是Environment提供
默认系统变量识别符。首先需要将对应系统属性绑定到AppStorage中,再通过AppStorage中的方法或者装饰器访问对应系统的
属性数据。
accessibilityEnabled是Environment提供
的系统默认变量识别符。首先需要将对应系统属性绑定到AppStorage上,再通过AppStorage中的方法或者装饰器访问对应的系统
属性数据。
\ No newline at end of file
zh-cn/application-dev/quick-start/arkts-state-mgmt-concepts.md
浏览文件 @
ba673c62
# 基本概念
ArkTS提供了多维度的状态管理机制,在
UI开发框架中,和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之前,也可以时全局范围内的传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活的
利用这些能力来实现数据和UI的联动。
ArkTS提供了多维度的状态管理机制,在
ArkUI开发框架中,和UI相关联的数据,不仅可以在组件内使用,还可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,也可以是应用全局范围内的传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活地
利用这些能力来实现数据和UI的联动。
![](
figures/CoreSpec_figures_state-mgmt-overview.png
)
...
...
@@ -11,20 +11,20 @@ ArkTS提供了多维度的状态管理机制,在UI开发框架中,和UI相
| 装饰器 | 装饰内容 | 说明 |
| ----------- | ------------------------- | ------------------------------------------------------------ |
| @State | 基本数据类型,类,数组 | 修饰的状态数据被修改时会触发组件的build方法进行UI界面更新。 |
| @Prop | 基本数据类型 | 修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,
更新当前组件的UI
。 |
| @Prop | 基本数据类型 | 修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,
当前组件会重新渲染
。 |
| @Link | 基本数据类型,类,数组 | 父子组件之间的双向数据绑定,父组件的内部状态数据作为数据源,任何一方所做的修改都会反映给另一方。 |
| @Observed | 类 | @Observed应用于类,表示该类中的数据变更被UI页面管理。 |
| @ObjectLink | 被@Observed所装饰类的对象 |
装饰的状态数据被修改时,在父组件或者其他兄弟组件内与它关联的状态数据所在的组件都会更新UI
。 |
| @ObjectLink | 被@Observed所装饰类的对象 |
@ObjectLink装饰的状态数据被修改时,在父组件或者其他兄弟组件内与它关联的状态数据所在的组件都会重新渲染
。 |
| @Consume | 基本数据类型,类,数组 | @Consume装饰的变量在感知到@Provide装饰的变量更新后,会触发当前自定义组件的重新渲染。 |
| @Provide | 基本数据类型,类,数组 | @Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。 |
| @Provide | 基本数据类型,类,数组 | @Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面
重新
渲染。 |
## 应用级变量的状态管理
AppStorage是整个
UI
应用程序状态的中心“数据库”,UI框架会针对应用程序创建单例AppStorage对象,并提供相应的装饰器和接口供应用程序使用。
AppStorage是整个应用程序状态的中心“数据库”,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提供了一系列应用程序需要的环境状态属性,这些属性
描述了应用程序运行的设备环境。
-
@StorageProp:@StorageProp(name)将UI组件
数据与AppStorage进行单向同步,AppStorage中值的更改会更新UI组件中的数据,但UI组件无法更改AppStorage中的数据
。
-
AppStorage还提供
了用于业务逻辑实现的API,用于添加、读取、修改和删除应用程序的状态数据
,此API所做的更改会导致修改的状态数据同步到UI组件上进行UI更新。
-
PersistentStorage
提供了一些静态方法用来管理应用持久化数据,可以将特定标记的持久化数据链接到AppStorage中,并由AppStorage接口访问对应持久化数据,或者通过@StorageLink装饰器来访问对应key的变量。
-
Environment是框架在应用程序启动时创建的单例对象,它为AppStorage提供了一系列应用程序需要的环境状态数据,这些数据
描述了应用程序运行的设备环境。
zh-cn/application-dev/quick-start/arkts-state-mgmt-page-level.md
浏览文件 @
ba673c62
此差异已折叠。
点击以展开。
zh-cn/application-dev/reference/arkui-ts/ts-state-management.md
浏览文件 @
ba673c62
此差异已折叠。
点击以展开。
zh-cn/application-dev/ui/Readme-CN.md
浏览文件 @
ba673c62
...
...
@@ -11,18 +11,15 @@
-
[
资源文件的分类
](
ui-ts-basic-resource-file-categories.md
)
-
[
资源访问
](
ts-resource-access.md
)
-
[
像素单位
](
ts-pixel-units.md
)
-
深入理解组件化
-
[
自定义组件初始化
](
ts-custom-component-initialization.md
)
-
[
自定义组件生命周期回调函数
](
ts-custom-component-lifecycle-callbacks.md
)
-
[
组件创建和重新初始化示例
](
ts-component-creation-re-initialization.md
)
-
常见组件开发指导
-
[
Button开发指导
](
ui-ts-basic-components-button.md
)
-
[
Web开发指导
](
ui-ts-components-web.md
)
-
常见布局开发指导
-
[
弹性布局
](
ui-ts-layout-flex.md
)
-
[
栅格布局
](
ui-ts-layout-grid-container.md
)
-
[
媒体查询
](
ui-ts-layout-mediaquery.md
)
-
[
Web组件开发
](
ui-ts-components-web.md
)
-
体验声明式UI
-
[
创建声明式UI工程
](
ui-ts-creating-project.md
)
-
[
初识Component
](
ui-ts-components.md
)
...
...
@@ -33,7 +30,6 @@
-
[
构建食物分类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
)
-
框架说明
...
...
zh-cn/application-dev/ui/ts-framework-directory.md
浏览文件 @
ba673c62
...
...
@@ -24,7 +24,7 @@ FA应用的ArkTS模块(entry/src/main)的典型开发目录结构如下:
> **说明:**
>
> - 资源目录resources文件夹位于src/main下,此目录下资源文件的详细规范以及子目录结构规范参看[资源文件的分类](ui-ts-basic-resource-file-categories.md)。
>- 页面支持导入TypeScript和JavaScript文件。
>
- 页面支持导入TypeScript和JavaScript文件。
**js标签配置:**
...
...
zh-cn/application-dev/ui/ui-ts-basic-components-button.md
已删除
100644 → 0
浏览文件 @
36d22833
# Button
Button是按钮组件,通常用于响应用户的点击操作,如提交表单,其类型包括胶囊按钮、圆形按钮、普通按钮。具体用法请参考
[
Button
](
../reference/arkui-ts/ts-basic-components-button.md
)
。
## 创建按钮
Button通过调用接口来创建,接口调用有以下两种形式:
-
创建包含子组件的按钮
`Button(options?: {type?: ButtonType, stateEffect?: boolean})`
,该接口用于创建包含子组件的按钮,其中type用于设置Button类型,stateEffect属性设置Button是否开启点击效果。
```
Button({ type: ButtonType.Normal, stateEffect: true }) {
Row() {
Image($r('app.media.loading')).width(20).height(20).margin({ left: 12 })
Text('loading').fontSize(12).fontColor(0xffffff).margin({ left: 5, right: 12 })
}.alignItems(VerticalAlign.Center)
}.borderRadius(8).backgroundColor(0x317aff).width(90)
```
!
[
zh-cn_image_0000001260555857
](
figures/zh-cn_image_0000001260555857.png
)
-
创建不包含子组件的按钮
`Button(label?: string, options?: { type?: ButtonType, stateEffect?: boolean })`
,该接口用于创建不包含子组件的按钮,其中label确定所创建的Button是否包含子组件。
```
Button('Ok', { type: ButtonType.Normal, stateEffect: true })
.borderRadius(8)
.backgroundColor(0x317aff)
.width(90)
```
!
[
zh-cn_image_0000001215796030
](
figures/zh-cn_image_0000001215796030.png
)
## 设置按钮类型
Button有三种可选类型,分别为Capsule(胶囊类型)、Circle(圆形按钮)和Normal(普通按钮),通过type进行设置。
-
胶囊按钮(默认类型)
```
ts
Button
(
'
Disable
'
,
{
type
:
ButtonType
.
Capsule
,
stateEffect
:
false
})
.
backgroundColor
(
0x317aff
)
.
width
(
90
)
```
!
[
zh-cn_image_0000001215645452
](
figures/zh-cn_image_0000001215645452.png
)
-
圆形按钮
```
ts
Button
(
'
Circle
'
,
{
type
:
ButtonType
.
Circle
,
stateEffect
:
false
})
.
backgroundColor
(
0x317aff
)
.
width
(
90
)
.
height
(
90
)
```
!
[
zh-cn_image_0000001215965420
](
figures/zh-cn_image_0000001215965420.png
)
## 自定义样式
-
设置边框弧度
一般使用通用属性来自定义按钮样式。例如通过borderRadius属性设置按钮的边框弧度。
```
ts
Button
(
'
circle border
'
,
{
type
:
ButtonType
.
Normal
})
.
borderRadius
(
20
)
```
!
[
zh-cn_image_0000001190463780
](
figures/zh-cn_image_0000001190463780.png
)
-
设置文本样式
通过添加文本样式设置按钮文本的展示样式。
```
ts
Button
(
'
font style
'
,
{
type
:
ButtonType
.
Normal
})
.
fontSize
(
20
)
.
fontColor
(
Color
.
Red
)
.
fontWeight
(
800
)
```
!
[
zh-cn_image_0000001189744672
](
figures/zh-cn_image_0000001189744672.png
)
-
设置背景颜色
添加backgroundColor属性设置按钮的背景颜色。
```
ts
Button
(
'
background color
'
).
backgroundColor
(
0xF55A42
)
```
!
[
zh-cn_image_0000001235146483
](
figures/zh-cn_image_0000001235146483.png
)
-
用作功能型按钮
为删除操作创建一个按钮。
```
ts
Button
({
type
:
ButtonType
.
Circle
,
stateEffect
:
true
})
{
Image
(
$r
(
'
app.media.ic_public_delete_filled
'
)).
width
(
30
).
height
(
30
)
}.
width
(
55
).
height
(
55
).
margin
({
left
:
20
}).
backgroundColor
(
0xF55A42
)
```
!
[
zh-cn_image_0000001260373911
](
figures/zh-cn_image_0000001260373911.png
)
## 添加事件
Button组件通常用于触发某些操作,可以在绑定onClick事件来响应点击操作后的自定义行为。
```
ts
Button
(
'
Ok
'
,
{
type
:
ButtonType
.
Normal
,
stateEffect
:
true
})
.
onClick
(()
=>
{
console
.
info
(
'
Button onClick
'
)
})
```
## 场景示例
-
用于启动操作
可以将按钮用于启动操作的任何用户界面元素。按钮会根据用户的操作触发相应的事件。如,在List容器里边通过点击按钮进行页面跳转:
```
ts
// xxx.ets
import
router
from
'
@ohos.router
'
@
Entry
@
Component
struct
ButtonCase1
{
build
()
{
List
({
space
:
4
})
{
ListItem
()
{
Button
(
"
First
"
).
onClick
(()
=>
{
router
.
push
({
url
:
'
xxx
'
})
})
}
ListItem
()
{
Button
(
"
Second
"
).
onClick
(()
=>
{
router
.
push
({
url
:
'
yyy
'
})
})
}
ListItem
()
{
Button
(
"
Third
"
).
onClick
(()
=>
{
router
.
push
({
url
:
'
zzz
'
})
})
}
}
.
listDirection
(
Axis
.
Vertical
)
.
backgroundColor
(
0xDCDCDC
).
padding
(
20
)
}
}
```
!
[
zh-cn_image_0000001235626467
](
figures/zh-cn_image_0000001235626467.png
)
-
用于表单的提交
在用户登录/注册页面,用户的登录或注册的提交操作会用按钮。
```
ts
// xxx.ets
@
Entry
@
Component
struct
ButtonCase2
{
build
()
{
Column
()
{
TextInput
({
placeholder
:
'
input your username
'
}).
margin
({
top
:
20
})
TextInput
({
placeholder
:
'
input your password
'
}).
type
(
InputType
.
Password
).
margin
({
top
:
20
})
Button
(
'
Register
'
).
width
(
300
).
margin
({
top
:
20
})
}.
padding
(
20
)
}
}
```
!
[
zh-cn_image_0000001190466492
](
figures/zh-cn_image_0000001190466492.png
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录