注意
- 默认情况下,应用只能访问有限的系统资源。其他资源权限处理https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/accesstoken-overview-0000001544703857-V3
.1、权限申请使用流程
应用配置文件概述(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配置文件
.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存在时才有意义(可缺省,缺省值为空)
常见的方式:
- 域名方式,如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"
}
}
}
语法
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。因此,在学习ArkTS语言之前,建议开发者具备TS语言开发能力。
当前,ArkTS在TS的基础上主要扩展了如下能力:
- 基本语法:ArkTS定义了声明式UI描述、自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架中的系统组件及其相关的事件方法、属性方法等共同构成了UI开发的主体。
- 状态管理:ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。另外,从数据的传递形式来看,可分为只读的单向传递和可变更的双向传递。开发者可以灵活地利用这些能力来实现数据和UI的联动。
- 渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。
.1、基本语法概述
- 装饰器: 用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中@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变量和内置组件的内部状态保持同步。