鸿蒙App语法/结构/注意

注意

.1、权限申请使用流程

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/accesstoken-overview-0000001544703857-V3#ZH-CN_TOPIC_0000001574088913__权限申请使用的工作流程

应用配置文件概述(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,
    }
  },
}

.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存在时才有意义(可缺省,缺省值为空)

常见的方式:

.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"
    }
  }
}

语法

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}`)

.2.2、配置属性

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

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

.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)

.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!');
      })
  }
}

.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!';
        })
    }
  }
}
.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')
    }
    }

  • 不允许声明本地变量,反例如下。

    build() {
    // 反例:不允许声明本地变量
    let a: number = 1;
    }

  • 不允许在UI描述里直接使用console.info,但允许在方法或者函数里使用,反例如下

    build() {
    // 反例:不允许console.info
    console.info('print debug log');
    }

  • 不允许创建本地的作用域,反例如下

    build() {
    // 反例:不允许本地作用域
    {
    ...
    }
    }

  • 不允许调用没有用@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())
      }
    }
    

    }

  • 不允许switch语法,如果需要使用条件判断,请使用if。反例如下

    build() {
    Column() {
    // 反例:不允许使用switch语法
    switch (expression) {
    case 1:
    Text('...')
    break;
    case 2:
    Image('...')
    break;
    default:
    Text('...')
    break;
    }
    }
    }

  • 不允许使用表达式,反例如下

    build() {
    Column() {
    // 反例:不允许使用表达式
    (this.aVar > 10) ? Text('...') : Image('...')
    }
    }

.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)
    }
  }
}

.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';
      })
    }
  }
}
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)
    }
  }
}

.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 })
      }
    }
    

    }

  • @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 })
      }
    }
    

    }

  • 在自定义组件中使用@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';
          })
        }
      }
    }
    

    }

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

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

  • 当前@Styles仅支持通用属性和通用事件。

  • @Styles方法不支持参数,反例如下。

    // 反例: @Styles不支持参数
    @Styles function globalFancy (value: number) {
    .width(value)
    }

  • @Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。

    // 全局
    @Styles function functionName() { ... }

    // 在组件内
    @Component
    struct FancyUse {
    @Styles fancy() {
    .height(100)
    }
    }

  • 定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值,示例如下:

    @Component
    struct FancyUse {
    @State heightValue: number = 100
    @Styles fancy() {
    .height(this.heightValue)
    .backgroundColor(Color.Yellow)
    .onClick(() => {
    this.heightValue = 200
    })
    }
    }

  • 组件内@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)
    }
  }
}

.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()
    }

  • 和@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)
    }
    }
    }

  • @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))
      }
    }
    

    }

  • @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
    })
    }
    }
    }

.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%')
    }
    }


@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)之间的关系。

  • 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 })
    }
    }
    }

  • 初始化子节点:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。示例同上。

  • 本地初始化:在变量声明的时候赋值,作为变量的默认值。示例:@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变量和内置组件的内部状态保持同步。

相关推荐
SameX37 分钟前
鸿蒙 Next 电商应用安全支付与密码保护实践
前端·harmonyos
SuperHeroWu71 小时前
【HarmonyOS】键盘遮挡输入框UI布局处理
华为·harmonyos·压缩·keyboard·键盘遮挡·抬起
sanzk6 小时前
华为鸿蒙应用开发
华为·harmonyos
SoraLuna10 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析11 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg66811 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
模拟IC攻城狮12 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
lqj_本人12 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人12 小时前
使用 Flutter 绘制一个棋盘
harmonyos
TangKenny12 小时前
计算网络信号
java·算法·华为