赞
踩
https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/application-configuration-file-overview-stage-0000001428061460-V3
在基于Stage模型开发的应用项目代码下,都存在一个app.json5及一个或多个module.json5这两种配置文件。
app.json5主要包含以下内容:
module.json5主要包含以下内容:
标签的值命名规则 :
推荐采用反域名形式命名(如com.example.demo,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。
该标签可选值为app和atomicService :
此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。该标签不可缺省,versionCode值应小于2^31次方。
该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。
第一段:主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。
第二段:次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加或大问题修复。
第三段:特性版本号/Feature,范围0-99,标识规划的新版本特性。
第四段:修订版本号/Patch,范围0-999,表示维护版本,修复bug。
标签最大字节长度为127。
取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。
该字段由DevEco Studio读取当前使用的SDK的Stage来生成。
多工程开发可以参考文档:多工程构建。
如果使用该属性对tablet设备做了特殊配置,则应用在tablet设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值
如果使用该属性对tv设备做了特殊配置,则应用在tv设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。
如果使用该属性对wearable设备做了特殊配置,则应用在wearable设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。
如果使用该属性对car设备做了特殊配置,则应用在car设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。
如果使用该属性对phone设备做了特殊配置,则应用在phone设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。
{ "app": { "bundleName": "com.application.myapplication", "vendor": "example", "versionCode": 1000000, "versionName": "1.0.0", "icon": "$media:app_icon", "label": "$string:app_name", "description": "$string:description_application", "minAPIVersion": 9, "targetAPIVersion": 9, "apiReleaseType": "Release", "debug": false, "car": { "minAPIVersion": 8, } }, }
标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一,仅支持英文字符。
类型有两种,分别:
标签值为字符串(最长为127字节)
标签值是字符串类型(最长255字节)或对描述内容的字符串资源索引。
标签值为字符串类型(最长为31个字节)。如果在HAP标签下配置了process,该应用的所有UIAbility、DataShareExtensionAbility、ServiceExtensionAbility都运行在该进程中。
说明:
标签最大字节长度为255。
标签值采用字符串数组的表示。
表示该Module对应的HAP是否跟随应用一起安装。
说明:
该标签值为字符串。如果目标虚拟机类型为ArkTS引擎,则其值为“ark+版本号”
该标签最大长度为255个字节。该标签是一个profile文件资源,用于指定描述页面信息的配置文件。
在开发视图的resources/base/profile下面定义配置文件main_pages.json,其中文件名(main_pages)可自定义,需要和前文中pages标签指定的信息对应,配置文件中列举了当前应用组件中的页面信息。
字符串类型(最大长度255字节)
标签值为字符串(最大长度255字节)。
标签值为标识该数据的资源的索引值。该标签最大字节长度为255字节。
abilities标签描述UIAbility组件的配置信息,标签值为数组类型,该标签下的配置只对当前UIAbility生效。
该名称在整个应用要唯一,标签值采用字符串表示(最大长度127个字节),仅支持英文字符。
标签值为字符串(最长为127字节)
可选标签值:
标签值是字符串类型(最长255字节)或对描述内容的资源索引,要求采用资源索引方式,以支持多语言。
标签值为图标资源文件的索引。
标签值配置为该名称的资源索引以支持多语言。
如果UIAbility被配置当前Module的mainElement时,该标签必须配置,且应用内唯一。
当其他应用访问该UIAbility时,需要申请相应的权限信息。
一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),取值为系统预定义的权限。
配置规则:
常见的方式:
如http默认端口为80,https默认端口是443,ftp默认端口是21。该字段要在schema和host都存在时才有意义。
path标识URI与want中的路径部分全匹配,pathStartWith标识URI与want中的路径部分允许前缀匹配,pathRegex标识URI与want中的路径部分允许正则匹配。该字段要在schema和host都存在时才有意义。
使用MIME(Multipurpose Internet Mail Extensions)类型规范。可与schema同时配置,也可以单独配置。
指定用于满足特定类型的长时任务。
长时任务类型有如下:
取值示例:$media:icon。该标签最大字节长度为255
取值示例:$color:red。该标签最大字节长度为255
为布尔类型:
该方向的取值范围包括:
包含:
隐式查询时,优先级越高,UIAbility在返回列表越靠前。该标签取值为integer类型,取值范围0-10。数值越大,优先级越高
该标签最小取值为0。
该标签最小取值为0
该标签最小取值为0。
该标签最小取值为0
该标签最小取值为0
该标签最小取值为0
说明:
标签值最大长度为127个字节,该名称在整个应用要唯一。
标签值最大长度为127字节
标签值最大长度为255字节,标签也可以是描述内容的资源索引,用于支持多语言。
标签值为资源文件的索引。如果ExtensionAbility组件被配置为MainElement,该标签必须配置。
标签值配置为该名称的资源索引以支持多语言。
说明:
取值为:
说明:
当其他应用访问该ExtensionAbility时,需要申请相应的权限信息。
一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),可以是系统预定义的权限,也可以是该应用自定义的权限。如果是后者,需与defPermissions标签中定义的某个权限的name标签值一致。
为字符数组类型(最大长度255),用反向域名的格式表示。
说明:
配置规则:entry包可以配置多个具有入口能力的skills标签(配置了ohos.want.action.home和entity.system.home)的ExtensionAbility,其中第一个配置了skills标签的ExtensionAbility中的label和icon作为应用或服务的label和icon。
说明:
为布尔类型。
说明:
描述权限使用的场景由abilities和when组成。其中abilities可以配置为多个UIAbility组件,when表示调用时机。
说明:
该标签最大字节长度为255个字节。
该标签最大字节长度为255个字节。
标签值为数组,最多可以配置四个快捷方式。其包含四个子标签shortcutId、label、icon、wants。
取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为255字节。
每个wants可配置bundleName和abilityName两个子标签。
distroFilter标签用于定义HAP对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括API Version、屏幕形状、屏幕尺寸、屏幕分辨率,设备的国家与地区码。在进行分发时,通过deviceType与这五个属性的匹配关系,唯一确定一个用于分发到设备的HAP。
该标签需要配置在/resource/profile资源目录下,并在模块的metadata的resource字段中引用。
配置为“exclude”或“include”。
场景示例:针对智能穿戴设备,可为圆形表盘和矩形表盘分别提供不同的HAP。
该字段仅支持对轻量级智能穿戴设备进行配置。
配置为“exclude”或“include”。
取值为整数像素值,例如“454 * 454”。
配置为“exclude”或“include”。
该标签为字符串数组,字符串范围如下。
具体值以ISO-3166-1标准为准。支持多个国家和地区枚举定义。
配置为“exclude”或“include”。
取值为整数像素值,例如“454 * 454”。
{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "mainElement": "EntryAbility", "deviceTypes": [ "tv", "tablet" ], "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", "virtualMachine": "ark", "metadata": [ { "name": "string", "value": "string", "resource": "$profile:distributionFilter_config" } ], "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ts", "launchType":"singleton", "description": "$string:description_main_ability", "icon": "$media:icon", "label": "Login", "permissions": [], "metadata": [], "exported": true, "continuable": true, "skills": [{ "actions": [ "ohos.want.action.home" ], "entities": [ "entity.system.home" ], "uris": [ { "scheme":"http", "host":"example.com", "port":"80", "path":"path", "type": "text/*" } ] }], "backgroundModes": [ "dataTransfer", "audioPlayback", "audioRecording", "location", "bluetoothInteraction", "multiDeviceConnection", "wifiInteraction", "voip", "taskKeeping" ], "startWindowIcon": "$media:icon", "startWindowBackground": "$color:red", "removeMissionAfterTerminate": true, "orientation": " ", "supportWindowMode": ["fullscreen", "split", "floating"], "maxWindowRatio": 3.5, "minWindowRatio": 0.5, "maxWindowWidth": 2560, "minWindowWidth": 1400, "maxWindowHeight": 300, "minWindowHeight": 200, "excludeFromMissions": false } ], "requestPermissions": [ { "name": "ohos.abilitydemo.permission.PROVIDER", "reason": "$string:reason", "usedScene": { "abilities": [ "FormAbility" ], "when": "inuse" } } ], "extensionAbilities": [ { "name": "FormName", "srcEntry": "./form/MyForm.ts", "icon": "$media:icon", "label" : "$string:extension_name", "description": "$string:form_description", "type": "form", "permissions": ["ohos.abilitydemo.permission.PROVIDER"], "readPermission": "", "writePermission": "", "exported": true, "uri":"scheme://authority/path/query", "skills": [{ "actions": [], "entities": [], "uris": [] }], "metadata": [ { "name": "ohos.extension.form", "resource": "$profile:form_config", } ] } ], "shortcuts": [ { "shortcutId": "id_test1", "label": "$string:shortcut", "icon": "$media:aa_icon", "wants": [ { "bundleName": "com.ohos.hello", "abilityName": "EntryAbility" } ] } ], "distroFilter": { "screenShape": { "policy": "include", "value": [ "circle", "rect" ] }, "screenWindow": { "policy": "include", "value": [ "454*454", "466*466" ] }, "screenDensity": { "policy": "exclude", "value": [ "ldpi", "xldpi" ] }, "countryCode": { // 支持中国和香港地区分发 "policy": "include", "value": [ "CN", "HK" ] } }, "testRunner": { "name": "myTestRunnerName", "srcPath": "etc/test/TestRunner.ts" } } }
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。
当前,ArkTS在TS的基础上主要扩展了如下能力:
除此之外,ArkTS扩展了多种语法范式来使开发更加便捷:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-declarative-ui-description-0000001524416537-V3
ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。
//无参数
Column() {
Text('item 1')
Divider()
Text('item 2')
}
// string类型的参数
Text('test')
// $r形式引入应用资源,可应用于多语言场景
Text($r('app.string.title_value'))
// 无参数形式
Text()
Image(this.imagePath)
Image('https://' + this.imageUrl)
Text(`count: ${this.count}`)
属性方法以“.”链式调用的方式配置系统组件的样式和其他属性,建议每个属性方法单独写一行。
Text('hello')
.fontSize(this.size)
Image('test.jpg')
.width(this.count % 2 === 0 ? 100 : 200)
.height(this.offset + 100)
//使用箭头函数配置组件的事件方法。 Button('Click me') .onClick(() => { this.myText = 'ArkUI'; }) //使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数体中的this指向当前组件。 Button('add counter') .onClick(function(){ this.counter += 2; }.bind(this)) //使用组件的成员函数配置组件的事件方法。 myClickHandler(): void { this.counter += 2; } ... Button('add counter') .onClick(this.myClickHandler.bind(this)) //使用声明的箭头函数,可以直接调用,不需要bind this fn = () => { console.info(`counter: ${this.counter}`) this.counter++ } ... Button('add counter') .onClick(this.fn)
如果组件支持子组件配置,则需在尾随闭包"{…}"中为组件添加子组件的UI描述。Column、Row、Stack、Grid、List等组件都是容器组件。
//以下是简单的Column组件配置子组件的示例。 Column() { Text('Hello') .fontSize(100) Divider() Text(this.myText) .fontSize(100) .fontColor(Color.Red) } //容器组件均支持子组件配置,可以实现相对复杂的多级嵌套。 Column() { Row() { Image('test1.jpg') .width(100) .height(100) Button('click +1') .onClick(() => { console.info('+1 clicked!'); }) } }
https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-create-custom-components-0000001473537046-V3
在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。
自定义组件具有以下特点:
如果在另外的文件中引用该自定义组件,需要使用export关键字导出,并在使用的页面import该自定义组件。
@Component
struct HelloComponent {
@State message: string = 'Hello, World!';
build() {
// HelloComponent自定义组件组合系统组件Row和Text
Row() {
Text(this.message)
.onClick(() => {
// 状态变量message的改变驱动UI刷新,UI从'Hello, World!'刷新为'Hello, ArkUI!'
this.message = 'Hello, ArkUI!';
})
}
}
}
自定义组件除了必须要实现build()函数外,还可以实现其他成员函数,成员函数具有以下约束:
自定义组件可以包含成员变量,成员变量具有以下约束:
所有声明在build()函数的语言,我们统称为UI描述,UI描述需要遵循以下规则:
@Entry @Component struct MyComponent { build() { // 根节点唯一且必要,必须为容器组件 Row() { ChildComponent() } } } @Component struct ChildComponent { build() { // 根节点唯一且必要,可为非容器组件 Image('test.jpg') } }
build() {
// 反例:不允许声明本地变量
let a: number = 1;
}
build() {
// 反例:不允许console.info
console.info('print debug log');
}
build() {
// 反例:不允许本地作用域
{
...
}
}
@Component struct ParentComponent { doSomeCalculations() { } calcTextValue(): string { return 'Hello World'; } @Builder doSomeRender() { Text(`Hello World`) } build() { Column() { // 反例:不能调用没有用@Builder装饰的方法 this.doSomeCalculations(); // 正例:可以调用 this.doSomeRender(); // 正例:参数可以为调用TS方法的返回值 Text(this.calcTextValue()) } } }
build() { Column() { // 反例:不允许使用switch语法 switch (expression) { case 1: Text('...') break; case 2: Image('...') break; default: Text('...') break; } } }
build() {
Column() {
// 反例:不允许使用表达式
(this.aVar > 10) ? Text('...') : Image('...')
}
}
自定义组件通过“.”链式调用的形式设置通用样式。
ArkUI给自定义组件设置样式时,相当于给MyComponent2套了一个不可见的容器组件,而这些样式是设置在容器组件上的,而非直接设置给MyComponent2的Button组件。通过渲染结果我们可以很清楚的看到,背景颜色红色并没有直接生效在Button上,而是生效在Button所处的开发者不可见的容器组件上。
@Component struct MyComponent2 { build() { Button(`Hello World`) } } @Entry @Component struct MyComponent { build() { Row() { MyComponent2() .width(200) .height(300) .backgroundColor(Color.Red) } } }
在开始之前,我们先明确自定义组件和页面的关系:
前面章节介绍了如何创建一个自定义组件。该自定义组件内部UI结构固定,仅与使用方进行数据传递。ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。‘
自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:
按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新。ArkUI提供$$作为按引用传递参数的范式。
ABuilder( $$ : { paramA1: string, paramB1 : string } ); @Builder function ABuilder($$: { paramA1: string }) { Row() { Text(`UseStateVarByReference: ${$$.paramA1} `) } } @Entry @Component struct Parent { @State label: string = 'Hello'; build() { Column() { // 在Parent组件中调用ABuilder的时候,将this.label引用传递给ABuilder ABuilder({ paramA1: this.label }) Button('Click me').onClick(() => { // 点击“Click me”后,UI从“Hello”刷新为“ArkUI” this.label = 'ArkUI'; }) } } }
调用@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起@Builder方法内的UI刷新。所以当使用状态变量的时候,推荐使用按引用传递。
@Builder function ABuilder(paramA1: string) {
Row() {
Text(`UseStateVarByValue: ${paramA1} `)
}
}
@Entry
@Component
struct Parent {
@State label: string = 'Hello';
build() {
Column() {
ABuilder(this.label)
}
}
}
https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-builderparam-0000001524416541-V3
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
///使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化@BuilderParam。 @Builder function GlobalBuilder0() {} @Component struct Child { @Builder doNothingBuilder() {}; @BuilderParam aBuilder0: () => void = this.doNothingBuilder; @BuilderParam aBuilder1: () => void = GlobalBuilder0; build(){} } ///用父组件自定义构建函数初始化子组件@BuilderParam装饰的方法。 @Component struct Child { @BuilderParam aBuilder0: () => void; build() { Column() { this.aBuilder0() } } } @Entry @Component struct Parent { @Builder componentBuilder() { Text(`Parent builder `) } build() { Column() { Child({ aBuilder0: this.componentBuilder }) } } } ///以下示例中,Parent组件在调用this.componentBuilder()时,this指向其所属组件,即“Parent”。@Builder componentBuilder()传给子组件@BuilderParam aBuilder0,在Child组件中调用this.aBuilder0()时,this指向在Child的label,即“Child”。 @Component struct Child { label: string = `Child` @BuilderParam aBuilder0: () => void; build() { Column() { this.aBuilder0() } } } @Entry @Component struct Parent { label: string = `Parent` @Builder componentBuilder() { Text(`${this.label}`) } build() { Column() { this.componentBuilder() Child({ aBuilder0: this.componentBuilder }) } } }
@Builder function GlobalBuilder1($$ : {label: string }) { Text($$.label) .width(400) .height(50) .backgroundColor(Color.Green) } @Component struct Child { label: string = 'Child' // 无参数类,指向的componentBuilder也是无参数类型 @BuilderParam aBuilder0: () => void; // 有参数类型,指向的GlobalBuilder1也是有参数类型的方法 @BuilderParam aBuilder1: ($$ : { label : string}) => void; build() { Column() { this.aBuilder0() this.aBuilder1({label: 'global Builder label' } ) } } } @Entry @Component struct Parent { label: string = 'Parent' @Builder componentBuilder() { Text(`${this.label}`) } build() { Column() { this.componentBuilder() Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 }) } } }
// xxx.ets @Component struct CustomContainer { @Prop header: string; @BuilderParam closer: () => void build() { Column() { Text(this.header) .fontSize(30) this.closer() } } } @Builder function specificParam(label1: string, label2: string) { Column() { Text(label1) .fontSize(30) Text(label2) .fontSize(30) } } @Entry @Component struct CustomContainerUser { @State text: string = 'header'; build() { Column() { // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包 // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数 CustomContainer({ header: this.text }) { Column() { specificParam('testA', 'testB') }.backgroundColor(Color.Yellow) .onClick(() => { this.text = 'changeHeader'; }) } } } }
@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。用于快速定义并复用自定义样式。
// 反例: @Styles不支持参数
@Styles function globalFancy (value: number) {
.width(value)
}
// 全局
@Styles function functionName() { ... }
// 在组件内
@Component
struct FancyUse {
@Styles fancy() {
.height(100)
}
}
@Component
struct FancyUse {
@State heightValue: number = 100
@Styles fancy() {
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
}
以下示例中演示了组件内@Styles和全局@Styles的用法
// 定义在全局的@Styles封装的样式 @Styles function globalFancy () { .width(150) .height(100) .backgroundColor(Color.Pink) } @Entry @Component struct FancyUse { @State heightValue: number = 100 // 定义在组件内的@Styles封装的样式 @Styles fancy() { .width(200) .height(this.heightValue) .backgroundColor(Color.Yellow) .onClick(() => { this.heightValue = 200 }) } build() { Column({ space: 10 }) { // 使用全局的@Styles封装的样式 Text('FancyA') .globalFancy () .fontSize(30) // 使用组件内的@Styles封装的样式 Text('FancyB') .fancy() .fontSize(30) } } }
在前文的示例中,可以使用@Styles用于样式的扩展,在@Styles的基础上,我们提供了@Extend,用于扩展原生组件样式。
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {
.fontSize(size)
.fancy()
}
// xxx.ets @Extend(Text) function fancy (fontSize: number) { .fontColor(Color.Red) .fontSize(fontSize) } @Entry @Component struct FancyUse { build() { Row({ space: 10 }) { Text('Fancy') .fancy(16) Text('Fancy') .fancy(24) } } }
@Extend(Text) function makeMeClick(onClick: () => void) { .backgroundColor(Color.Blue) .onClick(onClick) } @Entry @Component struct FancyUse { @State label: string = 'Hello World'; onClickHandler() { this.label = 'Hello ArkUI'; } build() { Row({ space: 10 }) { Text(`${this.label}`) .makeMeClick(this.onClickHandler.bind(this)) } } }
@Extend(Text) function fancy (fontSize: number) { .fontColor(Color.Red) .fontSize(fontSize) } @Entry @Component struct FancyUse { @State fontSizeValue: number = 20 build() { Row({ space: 10 }) { Text('Fancy') .fancy(this.fontSizeValue) .onClick(() => { this.fontSizeValue = 30 }) } } }
@Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。这就是我们本章要介绍的内容stateStyles(又称为:多态样式)。
stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:
@Entry @Component struct StateStylesSample { build() { Column() { Button('Button1') .stateStyles({ focused: { .backgroundColor(Color.Pink) }, pressed: { .backgroundColor(Color.Black) }, normal: { .backgroundColor(Color.Red) } }) .margin(20) Button('Button2') .stateStyles({ focused: { .backgroundColor(Color.Pink) }, pressed: { .backgroundColor(Color.Black) }, normal: { .backgroundColor(Color.Red) } }) }.margin('30%') } }
@Styles和stateStyles联合使用
以下示例通过@Styles指定stateStyles的不同状态。
@Entry @Component struct MyComponent { @Styles normalStyle() { .backgroundColor(Color.Gray) } @Styles pressedStyle() { .backgroundColor(Color.Red) } build() { Column() { Text('Text1') .fontSize(50) .fontColor(Color.White) .stateStyles({ normal: this.normalStyle, pressed: this.pressedStyle, }) } } }
stateStyles可以通过this绑定组件内的常规变量和状态变量。
@Entry @Component struct CompWithInlineStateStyles { @State focusedColor: Color = Color.Red; normalColor: Color = Color.Green build() { Column() { Button('clickMe').height(100).width(100) .stateStyles({ normal: { .backgroundColor(this.normalColor) }, focused: { .backgroundColor(this.focusedColor) } }) .onClick(() => { this.focusedColor = Color.Pink }) .margin('30%') } } }
Button默认normal态显示绿色,第一次按下Tab键让Button获焦显示为focus态的红色,点击事件触发后,再次按下Tab键让Button获焦,focus态变为粉色。
https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-state-management-overview-0000001524537145-V3
在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。
自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。 下图展示了State和View(UI)之间的关系。
@Component struct MyComponent { @State count: number = 0; private increaseBy: number = 1; build() { } } @Component struct Parent { build() { Column() { // 从父组件初始化,覆盖本地定义的默认值 MyComponent({ count: 1, increaseBy: 2 }) } } }
ArkUI提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察在组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:
从数据的传递形式和同步类型层面看,装饰器也可分为:
图示如下,具体装饰器的介绍,可详见管理组件拥有的状态和管理应用拥有的状态。开发者可以灵活地利用这些能力来实现数据和UI的联动。
上图中,Components部分的装饰器为组件级别的状态管理,Application部分为应用的状态管理。开发者可以通过@StorageLink/@LocalStorageLink实现应用和组件状态的双向同步,通过@StorageProp/@LocalStorageProp实现应用和组件状态的单向同步。
管理组件拥有的状态,即图中Components级别的状态管理:
管理应用拥有的状态,即图中Application级别的状态管理:
@Watch用于监听状态变量的变化。
$$运算符:给内置组件提供TS变量的引用,使得TS变量和内置组件的内部状态保持同步。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。