当前位置:   article > 正文

鸿蒙App语法/结构/注意_鸿蒙语法

鸿蒙语法

注意

.1、权限申请使用流程

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/accesstoken-overview-0000001544703857-V3#ZH-CN_TOPIC_0000001574088913__%E6%9D%83%E9%99%90%E7%94%B3%E8%AF%B7%E4%BD%BF%E7%94%A8%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B

应用配置文件概述(Stage模型)

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主要包含以下内容:

  • Module的基本配置信息,例如Module名称、类型、描述、支持的设备类型等基本信息。
  • 应用组件信息,包含UIAbility组件和ExtensionAbility组件的描述信息。
  • 应用运行过程中所需的权限信息。

.1、app.json5配置文件

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/app-configuration-file-0000001427584584-V3

.1.1、bundleName—标识应用的Bundle名称,用于标识应用的唯一性(该标签不可缺省)

标签的值命名规则 :

  • 字符串以字母、数字、下划线和符号“.”组成。
  • 以字母开头。
  • 最小长度7个字节,最大长度127个字节。

推荐采用反域名形式命名(如com.example.demo,建议第一级为域名后缀com,第二级为厂商/个人名,第三级为应用名,也可以多级)。

.1.2、bundleType—标识应用的Bundle类型,用于区分应用或者原子化服务(该标签可以缺省,缺省为app)

该标签可选值为app和atomicService :

  • app:当前Bundle为普通应用。
  • atomicService:当前Bundle为元服务。

.1.3、debug—标识应用是否可调试,该标签由IDE编译构建时生成(该标签可以缺省,缺省为false)

  • true:可调试。
  • false:不可调试。

.1.4、icon—标识应用的图标,标签值为图标资源文件的索引(该标签不可缺省)

.1.5、label—标识应用的名称,标签值为字符串资源的索引(该标签不可缺省)

.1.6、description—标识应用的描述信息,标签值是字符串类型(最大255个字节)或对描述内容的字符串资源索引(该标签可以缺省,缺省为空)

.1.7、vendor—标识对应用开发厂商的描述。该标签的值是字符串类型(最大255个字节)(该标签可以缺省,缺省为空)

.1.8、versionCode—标识应用的版本号,该标签值为32位非负整数(该标签不可缺省)

此数字仅用于确定某个版本是否比另一个版本更新,数值越大表示版本越高。开发者可以将该值设置为任何正整数,但是必须确保应用的新版本都使用比旧版本更大的值。该标签不可缺省,versionCode值应小于2^31次方。

.1.9、versionName—标识应用版本号的文字描述,用于向用户展示(该标签不可缺省)

该标签仅由数字和点构成,推荐采用“A.B.C.D”四段式的形式。四段式推荐的含义如下所示。
第一段:主版本号/Major,范围0-99,重大修改的版本,如实现新的大功能或重大变化。
第二段:次版本号/Minor,范围0-99,表示实现较突出的特点,如新功能添加或大问题修复。
第三段:特性版本号/Feature,范围0-99,标识规划的新版本特性。
第四段:修订版本号/Patch,范围0-999,表示维护版本,修复bug。
标签最大字节长度为127。

.1.10、minCompatibleVersionCode—标识应用能够兼容的最低历史版本号,用于跨设备兼容性判断(该标签可缺省,缺省值等于versionCode标签值)

.1.11、minAPIVersion—标识应用运行需要的SDK的API最小版本(由build-profile.json5中的compatibleSdkVersion生成)

.1.12、targetAPIVersion—标识应用运行需要的API目标版本(由build-profile.json5中的compatibleSdkVersion生成)

.1.13、apiReleaseType—标识应用运行需要的API目标版本的类型,采用字符串类型表示(该标签可缺省,由IDE生成并覆盖)

取值为“CanaryN”、“BetaN”或者“Release”,其中,N代表大于零的整数。

  • Canary:受限发布的版本。
  • Beta:公开发布的Beta版本。
  • Release:公开发布的正式版本。

该字段由DevEco Studio读取当前使用的SDK的Stage来生成。

.1.14、multiProjects—标识当前工程是否支持多个工程的联合开发(可缺省,缺省值为false)

  • true:当前工程支持多个工程的联合开发。
  • false:当前工程不支持多个工程的联合开发。

多工程开发可以参考文档:多工程构建

.1.15、tablet—标识对tablet设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled(该标签可缺省,缺省时tablet设备使用app.json5公共区域配置的属性值)

如果使用该属性对tablet设备做了特殊配置,则应用在tablet设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值

.1.16、tv—标识对tv设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled(该标签可缺省,缺省时tv设备使用app.json5公共区域配置的属性值)

如果使用该属性对tv设备做了特殊配置,则应用在tv设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。

.1.17、wearable—标识对wearable设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled(该标签可缺省,缺省时wearable设备使用app.json5公共区域配置的属性值)

如果使用该属性对wearable设备做了特殊配置,则应用在wearable设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。

.1.18、car—标识对car设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled(该标签可缺省,缺省时car设备使用app.json5公共区域配置的属性值)

如果使用该属性对car设备做了特殊配置,则应用在car设备中会采用此处配置的属性值,并忽略在app.json5公共区域配置的属性值。

.1.19、phone—标识对phone设备做的特殊配置,可以配置的属性字段有上文提到的:minAPIVersion、distributedNotificationEnabled(该标签可缺省,缺省时phone设备使用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,
    }
  },
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

.2、module.json5配置文件

.2.1、name—标识当前Module的名称(该标签不可缺省)

标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一,仅支持英文字符。

.2.2、type—标识当前Module的类型(该标签不可缺省)

类型有两种,分别:

  • entry:应用的主模块。
  • feature:应用的动态特性模块。

.2.3、srcEntry—标识当前Module所对应的代码路径(该标签可缺省,缺省值为空)

标签值为字符串(最长为127字节)

.2.4、description—标识当前Module的描述信息(该标签可缺省,缺省值为空)

标签值是字符串类型(最长255字节)或对描述内容的字符串资源索引。

.2.5、process—标识当前Module的进程名(可缺省,缺省为app.json5文件下app标签下的bundleName)

标签值为字符串类型(最长为31个字节)。如果在HAP标签下配置了process,该应用的所有UIAbility、DataShareExtensionAbility、ServiceExtensionAbility都运行在该进程中。

说明:

  • 仅支持系统应用配置,三方应用配置不生效。

.2.6、mainElement—标识当前Module的入口UIAbility名称或者ExtensionAbility名称(该标签可缺省,缺省值为空)

标签最大字节长度为255。

.2.7、deviceTypes—标识当前Module可以运行在哪类设备上(该标签不可缺省)

标签值采用字符串数组的表示。

.2.7.1、tablet—平板
.2.7.2、tv—智慧屏
.2.7.3、wearable—智能手表(系统能力较丰富的手表,具备电话功能)
.2.7.4、car—车机
.2.7.5、phone—手机

.2.8、deliveryWithInstall—标识当前Module是否在用户主动安装的时候安装(该标签不可缺省)

表示该Module对应的HAP是否跟随应用一起安装。

  • true:主动安装时安装。
  • false:主动安装时不安装。

.2.9、installationFree—标识当前Module是否支持免安装特性(该标签不可缺省)

  • true:表示支持免安装特性,且符合免安装约束。
  • false:表示不支持免安装特性。

说明:

  • 当应用的entry类型Module的该字段配置为true时,该应用的feature类型的该字段也需要配置为true。
  • 当应用的entry类型Module的该字段配置为false时,该应用的feature类型的该字段根据业务需求配置true或false。

.2.10、virtualMachine—标识当前Module运行的目标虚拟机类型,供云端分发使用,如应用市场和分发中心(该标签由IDE构建HAP的时候自动插入)

该标签值为字符串。如果目标虚拟机类型为ArkTS引擎,则其值为“ark+版本号”

.2.11、pages—标识当前Module的profile资源,用于列举每个页面信息(在有UIAbility的场景下,该标签不可缺省)

该标签最大长度为255个字节。该标签是一个profile文件资源,用于指定描述页面信息的配置文件。
在开发视图的resources/base/profile下面定义配置文件main_pages.json,其中文件名(main_pages)可自定义,需要和前文中pages标签指定的信息对应,配置文件中列举了当前应用组件中的页面信息。

.2.11.1、src—描述有关JavaScript模块中所有页面的路由信息,包括页面路径和页面名称。该值是一个字符串数组,其中每个元素表示一个页面(该标签不可缺省)
.2.11.2、window—用于定义与显示窗口相关的配置(该标签可缺省,缺省值为空)
.2.11.2.1、designWidth—标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小(可缺省,缺省值为720px)
.2.11.2.2、autoDesignWidth—标识页面设计基准宽度是否自动计算。当配置为true时,designWidth将会被忽略,设计基准宽度由设备宽度与屏幕密度计算得出(可缺省,缺省值为false)

.2.12、metadata—标识当前Module的自定义元信息,标签值为数组类型,只对当前Module、UIAbility、ExtensionAbility生效(该标签可缺省,缺省值为空)

.2.12.1、name—该标签标识数据项的键名称(该标签可缺省,缺省值为空)

字符串类型(最大长度255字节)

.2.12.2、value—该标签标识数据项的值(该标签可缺省,缺省值为空)

标签值为字符串(最大长度255字节)。

.2.13.2、resource—该标签标识定义用户自定义数据格式(该标签可缺省,缺省值为空)

标签值为标识该数据的资源的索引值。该标签最大字节长度为255字节。

.2.14、abilities—标识当前Module中UIAbility的配置信息,标签值为数组类型,只对当前UIAbility生效(该标签可缺省,缺省值为空)

abilities标签描述UIAbility组件的配置信息,标签值为数组类型,该标签下的配置只对当前UIAbility生效。

.2.14.1、name—标识当前UIAbility组件的名称(该标签不可缺省)

该名称在整个应用要唯一,标签值采用字符串表示(最大长度127个字节),仅支持英文字符。

.2.14.2、srcEntry—该标签标识入口UIAbility的代码路径(该标签不可缺省)

标签值为字符串(最长为127字节)

.2.14.3、launchType—标识当前UIAbility组件的启动模式(可缺省,该标签缺省为“singleton”)

可选标签值:

  • multiton:多实例模式,每次启动创建一个新的实例。
  • singleton:单实例模式,仅第一次启动创建新实例。
  • specified:指定实例模式,运行时由开发者决定是否创建新实例。
.2.14.4、description—标识当前UIAbility组件的描述信息(该标签可缺省,缺省值为空)

标签值是字符串类型(最长255字节)或对描述内容的资源索引,要求采用资源索引方式,以支持多语言。

.2.14.5、icon—标识当前UIAbility组件的图标(该标签可缺省,缺省值为空。如果UIAbility被配置为MainElement,该标签必须配置)

标签值为图标资源文件的索引。

.2.14.6、label—标识当前UIAbility组件对用户显示的名称(该标签不可缺省)

标签值配置为该名称的资源索引以支持多语言。
如果UIAbility被配置当前Module的mainElement时,该标签必须配置,且应用内唯一。

.2.14.7、permissions—标识当前UIAbility组件自定义的权限信息(该标签可缺省,缺省值为空)

当其他应用访问该UIAbility时,需要申请相应的权限信息。
一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),取值为系统预定义的权限。

.2.14.8、metadata—标识当前UIAbility组件的元信息(该标签可缺省,缺省值为空)
.2.14.9、exported—标识当前UIAbility组件是否可以被其他应用调用(该标签可缺省,缺省值为false)
  • true:表示可以被其他应用调用。
  • false:表示不可以被其他应用调用。
.2.14.10、continuable—标识当前UIAbility组件是否可以迁移(该标签可缺省,缺省值为空)
  • true:表示可以被迁移。
  • false:表示不可以被迁移。
.2.14.11、skills—标识当前UIAbility组件或ExtensionAbility组件能够接收的Want的特征集,为数组格式(该标签可缺省,缺省值为空)

配置规则:

  • 对于Entry类型的HAP,应用可以配置多个具有入口能力的skills标签(即配置了ohos.want.action.home和entity.system.home)。
  • 对于Feature类型的HAP,只有应用可以配置具有入口能力的skills标签,服务不允许配置。
.2.14.11.1、actions—标识能够接收的Want的Action值的集合,取值通常为系统预定义的action值,也允许自定义(可缺省,缺省值为空)
.2.14.11.2、entities—标识能够接收Want的Entity值的集合(可缺省,缺省值为空)
.2.14.11.3、uris—标识与Want中URI(Uniform Resource Identifier)相匹配的集合可缺省,缺省值为空)
.2.14.11.4、scheme—标识URI的协议名部分,常见的有http、https、file、ftp等(uris中仅配置type时可以缺省,缺省值为空,否则不可缺省)
.2.14.11.5、host—标识URI的主机地址部分,该字段要在schema存在时才有意义(可缺省,缺省值为空)

常见的方式:

  • 域名方式,如example.com。
  • IP地址方式,如10.10.10.1。
.2.14.11.6、port—标识URI的端口部分(可缺省,缺省值为空)

如http默认端口为80,https默认端口是443,ftp默认端口是21。该字段要在schema和host都存在时才有意义。

.2.14.11.7、path | pathStartWith | pathRegex—标识URI的路径部分,path、pathStartWith和pathRegex配置时三选一(可缺省,缺省值为空)

path标识URI与want中的路径部分全匹配,pathStartWith标识URI与want中的路径部分允许前缀匹配,pathRegex标识URI与want中的路径部分允许正则匹配。该字段要在schema和host都存在时才有意义。

.2.14.11.8、type—标识与Want相匹配的数据类型(可缺省,缺省值为空)

使用MIME(Multipurpose Internet Mail Extensions)类型规范。可与schema同时配置,也可以单独配置。

.2.14.12、backgroundModes—标识当前UIAbility组件的长时任务集合(该标签可缺省,缺省值为空)

指定用于满足特定类型的长时任务。

长时任务类型有如下:

  • dataTransfer:通过网络/对端设备进行数据下载、备份、分享、传输等业务。
  • audioPlayback:音频输出业务。
  • audioRecording:音频输入业务。
  • location:定位、导航业务。
  • bluetoothInteraction:蓝牙扫描、连接、传输业务(穿戴)。
  • multiDeviceConnection:多设备互联业务。
  • wifiInteraction:Wi-Fi扫描、连接、传输业务(克隆多屏)。
  • voip:音视频电话,VoIP业务。
  • taskKeeping:计算业务。
.2.14.13、startWindowIcon—标识当前UIAbility组件启动页面图标资源文件的索引(不可缺省)

取值示例:$media:icon。该标签最大字节长度为255

.2.14.14、startWindowBackground—标识当前UIAbility组件启动页面背景颜色资源文件的索引(不可缺省)

取值示例:$color:red。该标签最大字节长度为255

.2.14.15、removeMissionAfterTerminate—标识当前UIAbility组件销毁后是否从任务列表中移除任务(该标签可缺省,缺省值为false)

为布尔类型:

  • true表示销毁后移除任务。
  • false表示销毁后不移除任务
.2.14.15、orientation—标识当前UIAbility组件启动时的方向(该标签可缺省,缺省值为unspecified)

该方向的取值范围包括:

  • unspecified:未指定方向,由系统自动判断显示方向。
  • landscape:横屏。
  • portrait:竖屏。
  • landscape_inverted:反向横屏。
  • portrait_inverted:反向竖屏。
  • auto_rotation:随传感器旋转。
  • auto_rotation_landscape:传感器横屏旋转,包括了横屏和反向横屏。
  • auto_rotation_portrait:传感器竖屏旋转,包括了竖屏和反向竖屏。
  • auto_rotation_restricted:传感器开关打开,方向可随传感器旋转。
  • auto_rotation_landscape_restricted:传感器开关打开,方向可随传感器旋转为横屏, 包括了横屏和反向横屏。
  • auto_rotation_portrait_restricted:传感器开关打开,方向随可传感器旋转为竖屏, 包括了竖屏和反向竖屏。
  • locked:传感器开关关闭,方向锁定。
.2.14.16、supportWindowMode—标识当前UIAbility组件所支持的窗口模式(该标签可缺省,缺省值为[“fullscreen”, “split”, “floating”])

包含:

  • fullscreen:全屏模式。
  • split:分屏模式。
  • floating:悬浮窗模式。
.2.14.17、priority—标识当前UIAbility组件的优先级,仅支持系统应用配置,三方应用配置不生效(该标签可缺省,缺省值为0)

隐式查询时,优先级越高,UIAbility在返回列表越靠前。该标签取值为integer类型,取值范围0-10。数值越大,优先级越高

.2.14.18、maxWindowRatio—标识当前UIAbility组件支持的最大的宽高比(该标签可缺省,缺省值为平台支持的最大的宽高比)

该标签最小取值为0。

.2.14.19、minWindowRatio—标识当前UIAbility组件支持的最小的宽高比(该标签可缺省,缺省值为平台支持的最小的宽高比)

该标签最小取值为0

.2.14.20、maxWindowWidth—标识当前UIAbility组件支持的最大的窗口宽度,宽度单位为vp(该标签可缺省,缺省值为平台支持的最大的窗口宽度)

该标签最小取值为0。

.2.14.21、minWindowWidth—标识当前UIAbility组件支持的最小的窗口宽度, 宽度单位为vp(该标签可缺省,缺省值为平台支持的最小的窗口宽度)

该标签最小取值为0

.2.14.22、maxWindowHeight—标识当前UIAbility组件支持的最大的窗口高度, 高度单位为vp(该标签可缺省,缺省值为平台支持的最大的窗口高度)

该标签最小取值为0

.2.14.23、minWindowHeight—标识当前UIAbility组件支持的最小的窗口高度, 高度单位为vp(该标签可缺省,缺省值为平台支持的最小的窗口高度)

该标签最小取值为0

.2.14.24、excludeFromMissions—标识当前UIAbility组件是否在最近任务列表中显示(该标签可缺省,缺省值为false)
  • true:表示不在任务列表中显示。
  • false:表示在任务列表中显示。

说明:

  • 仅支持系统应用配置,三方应用配置不生效。

.2.15、extensionAbilities—标识当前Module中ExtensionAbility的配置信息,标签值为数组类型,只对当前ExtensionAbility生效(该标签可缺省,缺省值为空)

.2.15.1、name—标识当前ExtensionAbility组件的名称(该标签不可缺省)

标签值最大长度为127个字节,该名称在整个应用要唯一。

.2.15.2、srcEntry—标识当前ExtensionAbility组件所对应的代码路径(该标签不可缺省)

标签值最大长度为127字节

.2.15.3、description—标识当前ExtensionAbility组件的描述(该标签可缺省,缺省值为空)

标签值最大长度为255字节,标签也可以是描述内容的资源索引,用于支持多语言。

.2.15.4、icon—标识当前ExtensionAbility组件的图标(该标签可缺省,缺省值为空)

标签值为资源文件的索引。如果ExtensionAbility组件被配置为MainElement,该标签必须配置。

.2.15.5、label—标识当前ExtensionAbility组件对用户显示的名称(该标签不可缺省)

标签值配置为该名称的资源索引以支持多语言。
说明:

  • 如果ExtensionAbility被配置当前Module的mainElement时,该标签必须配置,且应用内唯一。
.2.15.6、type—标识当前ExtensionAbility组件的类型(该标签不可缺省)

取值为:

  • form:卡片的ExtensionAbility。
  • workScheduler:延时任务的ExtensionAbility。
  • inputMethod:输入法的ExtensionAbility。
  • service:后台运行的service组件。
  • accessibility:辅助能力的ExtensionAbility。
  • dataShare:数据共享的ExtensionAbility。
  • fileShare:文件共享的ExtensionAbility。
  • staticSubscriber:静态广播的ExtensionAbility。
  • wallpaper:壁纸的ExtensionAbility。
  • backup:数据备份的ExtensionAbility。
  • window:该ExtensionAbility会在启动过程中创建一个window,为开发者提供界面开发。开发者开发出来的界面将通过abilityComponent控件组合到其他应用的窗口中。
  • thumbnail:获取文件缩略图的ExtensionAbility,开发者可以对自定义文件类型的文件提供缩略。
  • preview:该ExtensionAbility会将文件解析后在一个窗口中显示,开发者可以通过将此窗口组合到其他应用窗口中。

说明:

  • 其中service和dataShare类型,仅支持系统应用配置,三方应用配置不生效。
.2.15.7、permissions—标识当前ExtensionAbility组件自定义的权限信息(该标签可缺省,缺省值为空)

当其他应用访问该ExtensionAbility时,需要申请相应的权限信息。

一个数组元素为一个权限名称。通常采用反向域名格式(最大255字节),可以是系统预定义的权限,也可以是该应用自定义的权限。如果是后者,需与defPermissions标签中定义的某个权限的name标签值一致。

.2.15.8、uri—标识当前ExtensionAbility组件提供的数据URI(该标签可缺省,缺省值为空)

为字符数组类型(最大长度255),用反向域名的格式表示。

说明:

  • 该标签在type为dataShare类型的ExtensionAbility时,不可缺省。
.2.15.9、skills—标识当前ExtensionAbility组件能够接收的Want的特征集,为数组格式(该标签可缺省,缺省值为空)

配置规则:entry包可以配置多个具有入口能力的skills标签(配置了ohos.want.action.home和entity.system.home)的ExtensionAbility,其中第一个配置了skills标签的ExtensionAbility中的label和icon作为应用或服务的label和icon。

说明:

  • 应用的Feature包可以配置具有入口能力的skills标签。
  • 服务的Feature包不能配置具有入口能力的skills标签。
.2.15.10、metadata—标识当前ExtensionAbility组件的元信息(该标签可缺省,缺省值为空)
.2.15.11、exported—标识当前ExtensionAbility组件是否可以被其他应用调用(该标签可缺省,缺省值为false)

为布尔类型。

  • true:表示可以被其他应用调用。
  • false:表示不可以被其他应用调用。

.2.16、requestPermissions—标识当前应用运行时需向系统申请的权限集合(该标签可缺省,缺省值为空)

.2.16.1、name—必须,填写需要使用的权限名称
.2.16.2、reason—可选,当申请的权限为user_grant权限时此字段必填,用于描述申请权限的原因

说明:

  • 当申请的权限为user_grant权限时,如果未填写该字段则不允许在应用市场上架,并且需要进行多语种适配。
.2.16.3、usedScene—可选,当申请的权限为user_grant权限时此字段必填(abilities:空。when:空。)

描述权限使用的场景由abilities和when组成。其中abilities可以配置为多个UIAbility组件,when表示调用时机。

说明:

  • 默认为可选,当申请的权限为user_grant权限时,abilities标签必填,when标签可选。

.2.17、testRunner—标识当前Module用于支持对测试框架的配置(该标签可缺省,缺省值为空)

.2.17.1、name—标识测试框架对象名称(不可缺省)

该标签最大字节长度为255个字节。

.2.17.2、srcPath—标识测试框架代码路径(不可缺省)

该标签最大字节长度为255个字节。

.2.18、shortcuts—标识应用的快捷方式信息

标签值为数组,最多可以配置四个快捷方式。其包含四个子标签shortcutId、label、icon、wants。

.2.18.1、shortcutId—标识快捷方式的ID。字符串的最大长度为63字节(该标签不可缺省)
.2.18.2、label—标识快捷方式的标签信息,即快捷方式对外显示的文字描述信息(该标签可缺省,缺省值为空)

取值可以是描述性内容,也可以是标识label的资源索引。字符串最大长度为255字节。

.2.18.3、icon—标识快捷方式的图标,标签值为资源文件的索引(该标签可缺省,缺省值为空)
.2.18.4、wants—标识快捷方式内定义的目标wants信息集合(该标签可缺省,缺省为空)

每个wants可配置bundleName和abilityName两个子标签。

  • bundleName:表示快捷方式的目标Bundle名称,字符串类型。
  • abilityName:表示快捷方式的目标组件名,字符串类型。

.2.19、distroFilter—该标签下的子标签均为可选字段,在应用市场云端分发时使用

distroFilter标签用于定义HAP对应的细分设备规格的分发策略,以便在应用市场进行云端分发应用包时做精准匹配。该标签可配置的分发策略维度包括API Version、屏幕形状、屏幕尺寸、屏幕分辨率,设备的国家与地区码。在进行分发时,通过deviceType与这五个属性的匹配关系,唯一确定一个用于分发到设备的HAP。

该标签需要配置在/resource/profile资源目录下,并在模块的metadata的resource字段中引用。

.2.19.1、apiVersion—标识支持的apiVersion范围(该标签可缺省,缺省值为空)
.2.19.2、screenShape—标识屏幕形状的支持策略(该标签可缺省,缺省值为空)
.2.19.2.1、policy—标识该子属性取值规则(该标签不可缺省)

配置为“exclude”或“include”。

  • exclude:表示需要排除的value属性。
  • include:表示需要包含的value属性。
.2.19.2.2、value—支持的取值为circle(圆形)、rect(矩形)(该标签不可缺省)

场景示例:针对智能穿戴设备,可为圆形表盘和矩形表盘分别提供不同的HAP。

.2.19.3、screenWindow—标识应用运行时窗口的分辨率支持策略(该标签可缺省,缺省值为空)

该字段仅支持对轻量级智能穿戴设备进行配置。

.2.19.3.1、policy—标识该子属性取值规则(该标签不可缺省)

配置为“exclude”或“include”。

  • exclude:表示该字段取值不包含value枚举值匹配规则的匹配该属性。
  • include:表示该字段取值满足value枚举值匹配规则的匹配该属性。
.2.19.3.2、value—单个字符串的取值格式为“宽 * 高”(该标签不可缺省)

取值为整数像素值,例如“454 * 454”。

.2.19.4、screenDensity—标识屏幕的像素密度(dpi:Dot Per Inch)(该标签可缺省,缺省值为空)
.2.19.4.1、policy—标识该子属性取值规则(该标签不可缺省)

配置为“exclude”或“include”。

  • exclude:表示需要排除的value属性。
  • include:表示需要包含的value属性。
.2.19.4.2、value—该标签标识屏幕的像素密度(dpi :Dot Per Inch)(该标签不可缺省)

该标签为字符串数组,字符串范围如下。

  • sdpi:表示小规模的屏幕密度(Small-scale Dots per Inch),适用于dpi取值为(0,120]的设备。
  • mdpi:表示中规模的屏幕密度(Medium-scale Dots Per Inch),适用于dpi取值为(120,160]的设备。
  • ldpi:表示大规模的屏幕密度(Large-scale Dots Per Inch),适用于dpi取值为(160,240]的设备。
  • xldpi:表示大规模的屏幕密度(Extra Large-scale Dots Per Inch),适用于dpi取值为(240,320]的设备。
  • xxldpi:表示大规模的屏幕密度(Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(320,480]的设备。
  • xxxldpi:表示大规模的屏幕密度(Extra Extra Extra Large-scale Dots Per Inch),适用于dpi取值为(480, 640]的设备。
.2.19.5、countryCode—表示应用需要分发的国家地区码(该标签可缺省,缺省值为空)

具体值以ISO-3166-1标准为准。支持多个国家和地区枚举定义。

.2.19.5.1、policy—标识该子属性取值规则(该标签不可缺省)

配置为“exclude”或“include”。

  • exclude:表示需要排除的value属性。
  • include:表示需要包含的value属性。
.2.19.5.2、value—标识应用需要分发的国家地区码(该标签不可缺省)

取值为整数像素值,例如“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"
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162

语法

ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。

当前,ArkTS在TS的基础上主要扩展了如下能力:

  • 基本语法:ArkTS定义了声明式UI描述、自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架中的系统组件及其相关的事件方法、属性方法等共同构成了UI开发的主体。
  • 状态管理:ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活地利用这些能力来实现数据和UI的联动。
  • 渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。

.1、基本语法概述

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-basic-syntax-overview-0000001531611153-V3

  • 装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新。
  • UI描述:以声明式的方式来描述UI的结构,例如build()方法中的代码块。
  • 自定义组件:可复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Hello。
  • 系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被开发者调用,比如示例中的Column、Text、Divider、Button。
  • 属性方法:组件可以通过链式调用配置多项属性,如fontSize()、width()、height()、backgroundColor()等。
  • 事件方法:组件可以通过链式调用设置多个事件的响应逻辑,如跟随在Button后面的onClick()。
  • 系统组件、属性方法、事件方法具体使用可参考基于ArkTS的声明式开发范式。

除此之外,ArkTS扩展了多种语法范式来使开发更加便捷:

  • @Builder/@BuilderParam:特殊的封装UI描述的方法,细粒度的封装和复用UI描述。
  • @Extend/@Styles:扩展内置组件和封装属性样式,更灵活地组合内置组件。
    stateStyles:多态样式,可以依据组件的内部状态的不同,设置不同样式。
    在这里插入图片描述

.2、声明式UI描述

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-declarative-ui-description-0000001524416537-V3
ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。

.2.1、创建组件

//无参数
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}`)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

.2.2、配置属性

属性方法以“.”链式调用的方式配置系统组件的样式和其他属性,建议每个属性方法单独写一行。

Text('hello')
  .fontSize(this.size)
Image('test.jpg')
  .width(this.count % 2 === 0 ? 100 : 200)    
  .height(this.offset + 100)
  • 1
  • 2
  • 3
  • 4
  • 5

.2.3、配置事件

//使用箭头函数配置组件的事件方法。
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

.2.4、配置子组件

如果组件支持子组件配置,则需在尾随闭包"{…}"中为组件添加子组件的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!');
      })
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

.3、自定义组件

.3.1、创建自定义组件

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-create-custom-components-0000001473537046-V3
在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。

自定义组件具有以下特点:

  • 可组合:允许开发者组合使用系统组件、及其属性和方法。
  • 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
  • 数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。
.3.1.1、自定义组件的基本用法

如果在另外的文件中引用该自定义组件,需要使用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!';
        })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
.3.1.2、自定义组件的基本结构
  • struct:自定义组件基于struct实现,struct + 自定义组件名 + {…}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。
  • @Component:@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述UI,一个struct只能被一个@Component装饰。
  • build()函数:build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。
  • @Entry:@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。@Entry可以接受一个可选的LocalStorage的参数。
.3.1.3、成员函数/变量

自定义组件除了必须要实现build()函数外,还可以实现其他成员函数,成员函数具有以下约束:

  • 不支持静态函数。
  • 成员函数的访问是私有的。

自定义组件可以包含成员变量,成员变量具有以下约束:

  • 不支持静态成员变量。
  • 所有成员变量都是私有的,变量的访问规则与成员函数的访问规则相同。
  • 自定义组件的成员变量本地初始化有些是可选的,有些是必选的。具体是否需要本地初始化,是否需要从父组件通过参数传递初始化子组件的成员变量,请参考状态管理。
.3.1.4、build()函数

所有声明在build()函数的语言,我们统称为UI描述,UI描述需要遵循以下规则:

  • @Entry装饰的自定义组件,其build()函数下的根节点唯一且必要,且必须为容器组件,其中ForEach禁止作为根节点。
    @Component装饰的自定义组件,其build()函数下的根节点唯一且必要,可以为非容器组件,其中ForEach禁止作为根节点。
@Entry
@Component
struct MyComponent {
  build() {
    // 根节点唯一且必要,必须为容器组件
    Row() {
      ChildComponent() 
    }
  }
}

@Component
struct ChildComponent {
  build() {
    // 根节点唯一且必要,可为非容器组件
    Image('test.jpg')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 不允许声明本地变量,反例如下。
build() {
  // 反例:不允许声明本地变量
  let a: number = 1;
}
  • 1
  • 2
  • 3
  • 4
  • 不允许在UI描述里直接使用console.info,但允许在方法或者函数里使用,反例如下
build() {
  // 反例:不允许console.info
  console.info('print debug log');
}
  • 1
  • 2
  • 3
  • 4
  • 不允许创建本地的作用域,反例如下
build() {
  // 反例:不允许本地作用域
  {
    ...
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 不允许调用没有用@Builder装饰的方法,允许系统组件的参数是TS方法的返回值
@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())
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 不允许switch语法,如果需要使用条件判断,请使用if。反例如下
build() {
  Column() {
    // 反例:不允许使用switch语法
    switch (expression) {
      case 1:
        Text('...')
        break;
      case 2:
        Image('...')
        break;
      default:
        Text('...')
        break;
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 不允许使用表达式,反例如下
build() {
  Column() {
    // 反例:不允许使用表达式
    (this.aVar > 10) ? Text('...') : Image('...')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
.3.1.5、自定义组件通用样式

自定义组件通过“.”链式调用的形式设置通用样式。

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)
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

.3.2、页面和自定义组件生命周期

在开始之前,我们先明确自定义组件和页面的关系:

  • 自定义组件:@Component装饰的UI单元,可以组合多个系统组件实现UI的复用,可以调用组件的生命周期。
  • 页面:即应用的UI页面。可以由一个或者多个自定义组件组成,@Entry装饰的自定义组件为页面的入口组件,即页面的根节点,一个页面有且仅能有一个@Entry。只有被@Entry装饰的组件才可以调用页面的生命周期。
    在这里插入图片描述

.4、注解相关

.4.1、@Builder装饰器:自定义构建函数

前面章节介绍了如何创建一个自定义组件。该自定义组件内部UI结构固定,仅与使用方进行数据传递。ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。‘

  • 允许在自定义组件内定义一个或多个@Builder方法,该方法被认为是该组件的私有、特殊类型的成员函数。
  • 自定义构建函数可以在所属组件的build方法和其他自定义构建函数中调用,但不允许在组件外调用。
  • 在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。
  • 全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。
  • 如果不涉及组件状态变化,建议使用全局的自定义构建方法。
.4.1.1、参数传递规则

自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:

  • 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
  • 在自定义构建函数内部,不允许改变参数值。如果需要改变参数值,且同步回调用点,建议使用@Link。
  • @Builder内UI语法遵循UI语法规则。
  • 只有传入一个参数,且参数需要直接传入对象字面量才会按引用传递该参数,其余传递方式均为按值传递。
.4.1.1.1、按引用传递参数

按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@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';
      })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
4.1.1.2、按值传递参数

调用@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)
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

.4.2、@BuilderParam装饰器:引用@Builder函数

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-builderparam-0000001524416541-V3
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

  • @BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。
///使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化@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 })
    }
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • @BuilderParam装饰的方法可以是有参数和无参数的两种形式,需与指向的@Builder方法类型匹配。@BuilderParam装饰的方法类型需要和@Builder方法类型一致。
@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 })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 在自定义组件中使用@BuilderParam装饰的属性时也可通过尾随闭包进行初始化。在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。
// 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';
        })
      }
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

.4.3、@Styles装饰器:定义组件重用样式

@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。用于快速定义并复用自定义样式。

  • 当前@Styles仅支持通用属性和通用事件。
  • @Styles方法不支持参数,反例如下。
// 反例: @Styles不支持参数
@Styles function globalFancy (value: number) {
  .width(value)
}
  • 1
  • 2
  • 3
  • 4
  • @Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。
// 全局
@Styles function functionName() { ... }

// 在组件内
@Component
struct FancyUse {
  @Styles fancy() {
    .height(100)
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值,示例如下:
@Component
struct FancyUse {
  @State heightValue: number = 100
  @Styles fancy() {
    .height(this.heightValue)
    .backgroundColor(Color.Yellow)
    .onClick(() => {
      this.heightValue = 200
    })
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 组件内@Styles的优先级高于全局@Styles。框架优先找当前组件内的@Styles,如果找不到,则会全局查找。

以下示例中演示了组件内@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)
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

.4.4、@Extend装饰器:定义扩展组件样式

在前文的示例中,可以使用@Styles用于样式的扩展,在@Styles的基础上,我们提供了@Extend,用于扩展原生组件样式。

  • 和@Styles不同,@Extend仅支持定义在全局,不支持在组件内部定义。
  • 和@Styles不同,@Extend支持封装指定的组件的私有属性和私有事件和预定义相同组件的@Extend的方法。
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
  .fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {
    .fontSize(size)
    .fancy()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。
// 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)
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • @Extend装饰的方法的参数可以为function,作为Event事件的句柄。
@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))
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • @Extend的参数可以为状态变量,当状态变量改变时,UI可以正常的被刷新渲染。
@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
        })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

.4.5、stateStyles:多态样式

@Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。这就是我们本章要介绍的内容stateStyles(又称为:多态样式)。

stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:

  • focused:获焦态。
  • normal:正常态。
  • pressed:按压态。
  • disabled:不可用态。
@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%')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

在这里插入图片描述
@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,
        })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这里插入图片描述
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%')
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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)之间的关系。
在这里插入图片描述

  • View(UI):UI渲染,指将build方法内的UI描述和@Builder装饰的方法内的UI描述映射到界面。
  • State:状态,指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。

.1、基本概念

  • 状态变量:被状态装饰器装饰的变量,状态变量值的改变会引起UI的渲染更新。示例:@State num: number = 1,其中,@State是状态装饰器,num是状态变量。
  • 常规变量:没有被状态装饰器装饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。以下示例中increaseBy变量为常规变量。
  • 数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。以下示例中数据源为count: 1。
  • 命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:CompA: ({ aProp: this.aProp })。
  • 从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。子组件初始化的默认值在有父组件传值的情况下,会被覆盖。示例:
@Component
struct MyComponent {
  @State count: number = 0;
  private increaseBy: number = 1;

  build() {
  }
}

@Component
struct Parent {
  build() {
    Column() {
      // 从父组件初始化,覆盖本地定义的默认值
      MyComponent({ count: 1, increaseBy: 2 })
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 初始化子节点:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。示例同上。
  • 本地初始化:在变量声明的时候赋值,作为变量的默认值。示例:@State count: number = 0。

.2、装饰器总览

ArkUI提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察在组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:

  • 管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。
  • 管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。

从数据的传递形式和同步类型层面看,装饰器也可分为:

  • 只读的单向传递;
  • 可变更的双向传递。

图示如下,具体装饰器的介绍,可详见管理组件拥有的状态和管理应用拥有的状态。开发者可以灵活地利用这些能力来实现数据和UI的联动。
在这里插入图片描述
上图中,Components部分的装饰器为组件级别的状态管理,Application部分为应用的状态管理。开发者可以通过@StorageLink/@LocalStorageLink实现应用和组件状态的双向同步,通过@StorageProp/@LocalStorageProp实现应用和组件状态的单向同步。

管理组件拥有的状态,即图中Components级别的状态管理:

  • @State:@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。
  • @Prop:@Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量是可变的,但修改不会同步回父组件。
  • @Link:@Link装饰的变量和父组件构建双向同步关系的状态变量,父组件会接受来自-@Link装饰的变量的修改的同步,父组件的更新也会同步给@Link装饰的变量。
  • @Provide/@Consume:@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
  • @Observed:@Observed装饰class,需要观察多层嵌套场景的class需要被@Observed装饰。单独使用@Observed没有任何作用,需要和@ObjectLink、@Prop连用。
  • @ObjectLink:@ObjectLink装饰的变量接收@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。

管理应用拥有的状态,即图中Application级别的状态管理:

  • AppStorage是应用程序中的一个特殊的单例LocalStorage对象,是应用级的数据库,和进程绑定,通过@StorageProp和@StorageLink装饰器可以和组件联动。
  • AppStorage是应用状态的“中枢”,将需要与组件(UI)交互的数据存入AppStorage,比如持久化数据PersistentStorage和环境变量Environment。UI再通过AppStorage提供的装饰器或者API接口,访问这些数据。
  • 框架还提供了LocalStorage,AppStorage是LocalStorage特殊的单例。LocalStorage是应用程序声明的应用状态的内存“数据库”,通常用于页面级的状态共享,通过@LocalStorageProp和@LocalStorageLink装饰器可以和UI联动。

.2.1、其他状态管理功能

@Watch用于监听状态变量的变化。
$$运算符:给内置组件提供TS变量的引用,使得TS变量和内置组件的内部状态保持同步。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/630078
推荐阅读
相关标签
  

闽ICP备14008679号