基于《2022重庆邮电大学-HarmonyOS移动应用开发》的学习【1-5】 原创 精华
【本文正在参与优质创作者激励】
Author:Hairtail
HarmonyOS移动应用开发课程链接
基于《2022重庆邮电大学-HarmonyOS移动应用开发》的学习【6-11】
一、初识HarmonyOS
武汉大学计算机学院 赵小刚
(一)HarmonyOS简介
- HarmonyOS是面向未来的全场景分布式操作系统
- 以手机为核心,构建1+8+N全场景应用
- 经典场景:
- 全新办公模式(手机-PC)
- 跨设备信息流转(手机-手表)
(二)HarmonyOS架构与安全
1.HarmonyOS架构
- 内核层(多内核设计):
- 包括内核子系统(进程/线程管理、内存管理、文件系统、网络管理、外设管理)
- 驱动子系统(提供统一外设访问能力和驱动开发管理框架)
- 有KAL内核抽象层,屏蔽多内核差异
- 对于外设而言,不同外设和内核需要不同的HDF与之对应,但HarmonyOS提供了统一驱动框架,使得内核与驱动解耦
- 系统服务层:是根据不同设备形态的部署环境按粒度进行裁剪
- 框架层:
- 用户程序框架(支持不同语言)
- Ability框架(抽象的能力)
- UI框架(Java UI与Ark UI)
- 多语言框架API(支持软硬设备对外开放)
- 应用层:(由FA与PA组成)
- 系统应用
- 三方应用
2.HarmonyOS应用服务智能分发
- 基于FA/PA构建的新型应用生态,能够实现三方服务跨设备智能分发,提供一致、高效 的用户体验
- 核心在于分发平台
3.HarmonyOS系统安全
- 三个正确:
- 正确的人:分布式多设备协同认证
- 正确的设备:分布式终端上构建可信运行环境(TEE)
- 正确的数据:在流转过程中进行分级管理
(三)HarmonyOS关键特性
1.硬件互助,资源共享
- 主要依赖四大能力:
- 分布式软总线(无感自组网)
- 分布式设备虚拟化(多设备功能虚拟)
- 分布式数据管理(跨端访问数据)
- 分布式任务调度(支持远程操作)
CoAP协议:是嵌入式设备在网络不稳定时候的一种协议
2.一次开发,多端部署
- 主要依赖于:HarmonyOS框架层的设计
3.统一OS,弹性部署
- 主要依赖于:组件化、小型化设计
- 实现:
- 组件可有可无
- 组件可大可小
- 平台可大可小
(四)HarmonyOS生态
- 官方推广计划:
- HarmonyOS社区运营计划(主要是和51CTO HarmonyOS技术社区)
- 高校-百校种子计划、高校-千校万里行
- 学习资料与途径:
- HarmonyOS官网社区:https://www.harmonyos.com/cn/home/
- HarmonyOS应用开发文档:https://developer.harmonyos.com/cn/home/
- HarmonyOS设备开发文档: https://device.harmonyos.com/cn/home/
- OpenHarmony开源地址: https://gitee.com/openharmony
- 华为人才在线: https://e.huawei.com/cn/talent/#/
(五)测一测
1.√
2.硬件形态和需求、硬件资源情况和功能需求、编译链关系
3.内核层
4.√
5.√
6.√
7.分布式软总线、分布式数据管理、分布式任务调度、方舟多语言运行时
8.正确的人、通过正确的设备、正确地使用数据
二、HarmonyOS开发工具DevEco Studio介绍
武汉大学计算机学院 赵小刚
(一)DevEco 基本特性
-
简介:DevEco Studio是基于IDEA开源版本打造的面向华为终端全场景多设备的一站式集成开发环境(IDE)
-
特性
- 多设备统一开发环境
- 支持多语言的代码开发和调试
- 支持FA和PA快速开发
- 支持分布式多端应用开发
- 支持多设备模拟器
- 支持多设备预览器
-
开发流程:
- 开发准备->开发应用->编译构建->运行、调试和测试应用->发布应用
(二)安装过程
- 搭建开发环境流程:
- (1)软件安装
- (2)配置开发环境
- (3)运行Hellword
(三)设置Gradle代理
- Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。
- 主要面向Java
- 主要依赖于(Apache ant:目标链控制、Gant、Apache maven:多项目模块插件管理、ivy:依赖管理)
- 项目自动化:防止开发手动介入,不依赖于操作系统的限制
- Android项目APK构建构成:
(四)Hello Word创建
- 工程模板丰富(手机、手环、座舱、平板)
- 按需创建项目(应用类型、语言、SDK版本等等)
- 项目在远程真机上运行(需要登录华为账号)
(五)JS项目基本结构
- 具体的可以看HarmonyOS官方文档-工程管理
- 需要了解:
- 项目文件结构
- entry模块结构
- 页面文件解析
- pages目录结构
(六)低代码开发
低代码开发的详细介绍可以看:清瑶-基于HarmonyOS低代码开发的学习与应用
(七)HarmonyOS App真机调试运行和上架
- 真机设备调试运行:(需要注意版本兼容问题)
- 应用分布流程:
(八)测一测
1.支持UI实时预览、支持多设备统一开发环境、支持分布式多端应用应用开发、支持多语言的代码开发和调试
2.支持界面的拖拽构建模式、支持业务逻辑js和界面相互绑定、支持界面自动生成hml和css代码
3.可以尽量防止开发手动介入从而节省了开发的时间并减少错误的发生、自动化可以自定义有序的步骤来完成代码的编译、测试和打包等工作,让重复的步骤变得简单
4.√
5.√
6.代码编写、编译构建、应用调试、应用发布
7.带调试签名信息的Debug类型的HAP、带调试签名信息的release类型的HAP、不带调试签名信息的Debug类型的HAP、不带调试签名信息的release类型的HAP
8.√
(九)知识补充
HAP按构建类型和是否签名可以分为以下四种形态:
1、带调试签名信息的Debug类型的HAP:携带调试签名信息,具备单步调试等调试手段的HAP,用于开发者在真机或者模拟器中进行应用调试。
2、不带调试签名信息的Debug类型的HAP:不带调试签名信息,具备单步调试等调试手段的HAP,仅能运行在模拟器中。
3、带调试签名信息的release类型的HAP:携带调试签名信息,不具备调试能力的HAP,用于开发者在真机或者模拟器中查看和验证应用运行效果。相对于Debug类型的HAP包,体积更小,运行效果与用户实际体验一致。
4、不带调试签名信息的release类型的HAP:不带调试签名信息,不具备调试能力的HAP,仅能运行在模拟器中查看和验证应用运行效果。相对于Debug类型的HAP包,体积更小,运行效果与用户实际体验一致。
三、HarmonyOS开发基础
(一)APP
- HarmonyOS的应用软件包以APP Pack(Application Package)形式发布,它是由一个 或多个HAP(HarmonyOS Ability Package)以及描述每个HAP属性的pack.info组成。 HAP是Ability的部署包,HarmonyOS应用代码围绕Ability组件展开
- 对于HAP
- 一个HAP是由代码、资源、第三方库及应用配置文件组成的模块包(分为entry和feature)
- HAP是由一个或多个Ability组成
HAP具体属性 | |
---|---|
属性名称 | 含义 |
delivery-with-install | 表示该HAP是否支持随应用安装。“true”表示支持随应用安装; “false”表示不支持随应用安装 |
name | HAP文件名 |
module-type | 模块类型,entry或feature |
device-type | 表示支持该HAP运行的设备类型 |
(二)Ability
- Ability是应用所具备的能力的抽象,一个应用可以包含一个或多个Ability。(PA、FA)
- 库文件是应用依赖的第三方代码(例如so、jar、bin、har等二进制文件),存放在libs目 录
- 配置文件 (config.json) 包含应用中Ability的配置信息,用于声明应用的Ability,以及应 用所需权限等信息
(三)库文件
- HAR(HarmonyOS Ability Resources)可以提供构建应用所需的所有内容,包括源代码、 资源文件和config.json文件。HAR不同于HAP,HAR不能独立安装运行在设备上,只能作为应用模块的依赖项被引用
(四)资源文件
- 应用的资源文件(字符串、图片、音频等)统一存放于resources目录下,便于开发者使 用和维护。resources目录包括base目录与限定词目录。
- 限定词目录:可以由一个或多个表征应用场景或设备特征的限定词组合而成(语言、文字、国家地区、横竖屏、设备类型)
- base目录限定词引用:在应用开发的hml和js文件中使用**$r的语法**,可以对JS模块内的resources目录下的json 资源进行格式化
(五)配置文件
这部分很复杂,但是不用太纠结,在之后的实际开发中慢慢熟悉即可
- 即config.json文件:
- 应用的全局配置信息,包含应用的包名、生产厂商、版本号等基本信息
- 应用在具体设备上的配置信息,包含应用的备份恢复、网络安全等能力
- HAP包的配置信息,包含每个Ability必须定义的基本属性(如包名、类名、类型以及Ability提供的能 力),以及应用访问系统或其他应用受保护部分所需的权限等
- config.json中必须包含三个部分:
- app
- deviceConfig
- module(必须包含一个主ability)
(六)HAR
- Module:是HarmonyOS应用的基本功能单元,每一个Module都可以独立进行编译和运行。每个Module分为 Ability和Library(HarmonyOS Library和Java Library)两种类型
- 创建HarmonyOS库的步骤
- 创建库模块
- 将库模块编译为HAR
- 发布Har包到Maven仓
- 为应用模块添加依赖
- 将库模块编译为HAR:利用Gradle可以将HarmonyOS Library库模块构建为HAR包。方法:在Gradle文件中,双击debugHarmonyHar或 releaseHarmonyHar任务,构建Debug类型或Release类型的HAR
- 如果要把HAR给别人用,就需要把HAR添加到Maven中
(七)测一测
1.√
2.代码、资源文件、第三方库、应用配置文件
3.√
4.standard、singleton、singleMisson
5.so、jar、bin、har
6.×
7.app、deviceConfig、moudle
8.√
(八)补充拓展
- 只有包含Ability的HAP才能够独立运行
- abilities->launchType表示Ability的启动模式
- standard:表示该Ability可以有多实例。“standard”模式适用于大多数应用场景。
- singleMission:表示此Ability在每个任务栈中只能有一个实例。
- singleton:表示该Ability在所有任务栈中仅可以有一个实例。例如,具有全局唯一性的呼叫来电界面即采用“singleton”模式。
四、HarmonyOS核心概念
武汉大学计算机学院 赵小刚
(一)Ability概念
- Ability是HarmonyOS应用程序的重要组成部分,分为FA(Feature Ability)和PA (Particle Ability)两种类型
- FA支持PA
- PA支持SA和DA
- 各Ability的作用
- FA:支持PA
- PA:提供与用户交互的能力
- SA:后台运行任务的能力
- DA:对外部提供统一的数据访问抽象
- 传统的MVC模式下的Ability之间的关系:
(二)page Ability
注意:PA是Particle Ability;Page Ability就是Page Ability
1.Page Ability与AbilitySlice的关系
- Page Ability与AbilitySlice的关系
- 一个Page Ability可以由一个或多个AbilitySlice
- 类似于蛋糕与蛋糕块,画板与画布的关系
- HarmonyOS支持不同Page之间的跳转,并且指定跳转到相应的AbilitySlice
2.AbilitySlice的路由配置
- AbilitySlice的路由配置
- (1)当Page进入前台时界面默认只展示一个AbilitySlice,即默认路由
- 默认路由由setMainRoute()方法指定
- (2)如果需要修改默认展示的AbilitySlice可以通过addAbilityRoute()方法为此AbilitySlice配置相应的路由
- (3)当Page实例期望导航到此AbilitySlice时,可以通过Intent中指定Action
- (1)当Page进入前台时界面默认只展示一个AbilitySlice,即默认路由
//setMainRoute设置MainSlice为默认路由
//addActionRoute添加PayAlipaySlice、PayWechatSlice两个AbilitySlice
//在同一Page里面进行页面跳转,在不同Page仅仅与此是不行的
public class MyAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
setMainRoute(MainSlice.class.getName());
addActionRoute("action.paybyAlipay",
PayAlipaySlice.class.getName());
addActionRoute("action.paybyWechat",
PayWechatSlice.class.getName());
}
}
- 暴露AbilitySlice
- 通过在config.json中注册
- 用Intent封装(intent相当于一个桥梁)
//config.json注册
{
"module": {
"abilities": [
{
"skills":[
{
"actions":[
"action.paybyAlipay",
"action.paybyWechat"
]
}
]
...
}
]
.. }
...}
//用intent封装
Intent intent = new Intent();
Operation operation = new
Intent.OperationBuilder()
.withAction(“action.paybyAlipay”)
.build();
intent.setOperation(operation);
startAbility (intent);
3.Page生命周期、AbilitySlice生命周期及两者的关联
- Page生命周期回调(通过回调感知状态,再处理工作)
- onStart(),首次创建Page实例时,触发该回调,在生命周期只触发一次
- onActive(),Page进入到INACTIVE状态后来到前台,然后系统调用此回调(过程是可以被打断的)
- onInactive(),当page失去焦点时调用
- onBackground(),如果Page不再对用户可见
- onForeground(),当处于BACKGROUND重新回到前台调用
- onStop(),
- (1)任务管理器关闭Page
- (2)用户行为触发Page的terminateAbility()方法调用
- (3)配置变更导致系统暂时销毁Page并重建
- (4)系统处于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁
- AbilitySlice实例化
- AbilitySlice生命周期与Page的相应回调类似,由于AbilitySlice承载具体的页面,开发者必须重写AbilitySlice的onStart()回调,并通过setUIContent()设置页面
- AbilitySlice实例创建和管理通常由应用负责,系统仅在特定情况下会创建AbilitySlice实 例
例如,通过导航启动某个AbilitySlice时,是由系统负责实例化;但是在同一个Page 中不同的AbilitySlice间导航时则由应用负责实例化
//AbilitySlice实例化
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
setUIContent(ResourceTable.Layout_main_layout);
}
- Page Ability与AbilitySlice生命周期关联
- 当AbilitySlice处于前台且具有焦点时,其生命周期状态随着所属Page的生命周期状态的 变化而变化
例如:MyAbility下有FooAbilitySlice 和BarAbilitySlice,当前FooAbilitySlice处于前台并获得焦点,并即将导航到 BarAbilitySlice,在此期间的生命周期状态变化顺序为:
(1)FooAbilitySlice从ACTIVE状态变为INACTIVE状态
(2)BarAbilitySlice则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前 BarAbilitySlice未曾启动)
(3)FooAbilitySlice从INACTIVE状态变为BACKGROUND状态
- 注意:在整个流程中,MyAbility始终处于ACTIVE状态。但是,当Page被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。
4.AbilitySlice间导航(同一Page、不同Page)
-
AbilitySlice间导航:
- 同一Page
- 不同Page
-
同一Page导航:
-
present()方法实现导航
-
@Override protected void onStart(Intent intent) { ... Button button = ...; button.setClickedListener(listener -> present(new TargetSlice(), new Intent())); }
-
AbilitySlice间数据传递:期望返回结果,则使用应当使 用**presentForResult()**实现导航,**onResult()**来接收和处理返回结果
-
//源侧AbilitySlice @Override protected void onStart(Intent intent) { ... Button button = ...; button.setClickedListener(listener -> presentForResult(new TargetSlice(), new Intent(), 0)); ... } @Override protected void onResult(int requestCode, Intent resultIntent) { if (requestCode == 0) { // Process resultIntent here. } }
-
AbilitySlice实例栈:
-
-
不同Page间导航:
- AbilitySlice作为Page的内部单元,以action的形式对外暴露,可以通过配置Intent的Action导航到目标AbilitySlice
- Page间的导航可 以使用**startAbility()或startAbilityForResult()**方法,获得返回结果的回调为 onAbilityResult()方法
(三)Service Ability
1.概述及生命周期
- SA主要用于后台运行任务,无交互界面,可以由其他应用或Ability启动,且是单实例在主线程执行。
- 创建SA(Service也需要在应用配置文件中进行注册,注册类型type需要设置为service),及其生命周期回调:
- onStart(),用于Service的初始化,在Service的整个生命周 期只会调用一次,调用时传入的Intent应为空
- onCommond(),在Service创建完成后,在客户端每次启动该Service时都会调用,可以做一些调用统计、初始化类的操作
- onDisconnect(),在Ability与绑定的Service断开连接时调用
- onStop():在Service销毁时调用,来清理任何资源,如关闭线 程、注册的侦听器
- onConnect()
- 只有第一个客户端连接Service时, 系统才会调用Service的onConnect方法来生成IRemoteObject对象
- 注意:而后系统会将同一 个RemoteObject对象传递至其他连接同一个Service的所有客户端连接,而无需再次调用 onConnect方法
在Ability和Service连接时调用,onConnect()方法返回IRemoteObject对象,用户可以在该回调函数中生成对应Service的IPC通信通道,以便Ability与Service交互。
IPC通信通道:进程间通信通道
2启动SA
- 通过了startAbility()方法来启动另外一个Ability,当然也可以启动SA,所以可以通过将Intent传递给该方法来启动Service。
- 设置目标Service信息:构造Operation对象,其中包含:
- DeviceId:表示设备ID。如果是本地设备,则可以直接留空;如果是远程设备,可以通过 ohos.distributedschedule.interwork.DeviceManager提供的getDeviceList获取设备列表
- BundleName:表示包名称
- AbilityName:表示待启动的Ability名称
//本地Service启动
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("com.huawei.hiworld.himusic")
.withAbilityName("com.huawei.hiworld.himusic.ServiceAbility")
.build();
intent.setOperation(operation);
startAbility(intent);
//远程Service启动
//相比之下就多了一个withFlags的信息
Operation operation = new Intent.OperationBuilder()
.withDeviceId("deviceId")
.withBundleName("com.huawei.hiworld.himusic")
.withAbilityName("com.huawei.hiworld.himusic.ServiceAbility")
// 设置支持分布式调度系统多设备启动的标识
.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
.build();
Intent intent = new Intent();
intent.setOperation(operation);
startAbility(intent);
- StartAbility的两种场景
- 如果Service尚未运行,则系统会先调用onStart()来初始化Service,再回调Service的 onCommand()方法来启动Service
- 如果Service正在运行,则系统会直接回调Service的onCommand()方法来启动Service
3.连接Service
- 启动Service的目的有两种:
- 启动起来以后就不管了
- 启动起来以后需要交互(这就需要通过用**connectAbility()**启动SA)
- 注意:客户端可通过调用 **disconnectAbility()**断开连接
- PPT里:
- 现行文档中:
4.前台Service
- 一般情况下,Service都是在后台运行的,后台Service的优先级都是比较低的,当资源不足时,系 统有可能回收正在运行的后台Service
- 特定场景(播放音乐),此时就需要使用前台Service。 前台Service会始终保持正在运行的图标在系统状态栏显示
- 使用前台Service,开发者只需在Service创建的方法里,调用**keepBackgroundRunning()**将Service与通知绑定
- 调用keepBackgroundRunning()方法前需要在配置文件中声明ohos.permission.KEEP_BACKGROUND_RUNNING权限
- 同时还需要在配置文件中添加对应的backgroundModes参数
- 在onStop()方法中调用cancelBackgroundRunning()方法可停止前台Service
// 创建通知,其中1005为notificationId
NotificationRequest request = new NotificationRequest(1005);
NotificationRequest.NotificationNormalContent content = new
NotificationRequest.NotificationNormalContent();
content.setTitle("title").setText("text");
NotificationRequest.NotificationContent notificationContent = new
NotificationRequest.NotificationContent(content);
request.setContent(notificationContent);
// 绑定通知,1005为创建通知时传入的notificationId
keepBackgroundRunning(1005, request);
(四)Intent
1.Intent的概念及分类
- Intent是对象之间传递信息的载体,构成元素包括Operation与Parameters
- Intent设置属性时,必须先使用Operation来设置属性。如果需要新增或修改属性,必须在设置Operation后再执行操作
- 当Intent用于发起请求时,根据指定元素的不同,分为两种类型:
- (显式Intent)如果同时指定了BundleName与AbilityName,则根据Ability的全称(例如“com.demoapp.FooAbility”)来直接启动应用
- (隐式Intent)如果未同时指定BundleName和AbilityName,则根据Operation中的其他属性来启动应用
2.通过显式Intent进行数据传递
- 场景:点击通讯录某人,跳转到某人的详情页
- FA1: secondIntent.setParam(“text”,“passedvalue”);
- 通过setParam可以在Intent中设置传递 给下一个页面的数据
- 这里是传递了一个字符串,名为text,值为passedvalue
- FA2: text.setText(intent.getStringParam(“text”));
- 在第二个页面的onStart(intent)方法中 可以调用getStringParam方法将字符串text值读出来
3.隐式Intent的使用
- 在不知道提供该能力的具体是哪一个应用时,则可以通过Operation的其他属性(除BundleName与 AbilityName之外的属性)描述需要的能力
- 如果设备上存在多个应用提供同种能力,系 统则弹出候选列表,由用户来进行选择
//请求方
//举例封装Intent、重写onAbilityResult()回调方法
//(1)封装Intent
private void queryWeather() {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(Intent.ACTION_QUERY_WEATHER)
.build();
intent.setOperation(operation);
startAbilityForResult(intent, REQ_CODE_QUERY_WEATHER);
}
//(2)重写onAbilityResult()回调方法
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
switch (requestCode) {
case REQ_CODE_QUERY_WEATHER:
// Do something with result.
...
return;
default:
...
}
}
//处理方
//配置文件修改、配置路由、处理请求
//(1)配置文件修改
{
"module": {
"abilities": [
{
"skills":[
{
"actions":[
"ability.intent.QUERY_WEATHER"
]
}
]
}
] }}
//(2)配置路由
@Override
protected void onStart(Intent intent) {
addActionRoute(Intent.ACTION_QUERY_WEATHER, DemoSlice.class.getName());
}
//(3)处理请求
@Override
protected void onActive() {
Intent resultIntent = new Intent();
setResult(0, resultIntent);
}
(五)访问后台服务获取电量Demo
-
流程:
- (1)建立前台FA显示电量信息
- (2)连接后台服务
- (3)建立后台服务BatteryInfo
- (4)封装IRemoteObject接口
- (5)建立IRemoteObject子类MyRemote的实例,并返回给onConnect函数
- (6)前台FA调用后台服务函数,显示电量
-
(2)连接后台服务
- 封装Intent
- 调用connectAbility(intent, connection)连接后台服务
-
(3)建立后台服务BatteryInfo
- 新建Service Ability
- 电量获取函数getBatteryInfo
- 完成Service Ability 的重载函数onConnect(Intent intent)
-
(4)IRemoteObject接口
-
@Override public IRemoteObject onConnect(Intent intent) { MyRemote thisRemote = new MyRemote(); thisRemote.butery = getBatteryInfo(); return thisRemote; }
-
-
(5)建立IRemoteObject子类MyRemote的实例,并返回给onConnect函数
- 新建MyRemote 类, MyRemote类为LocalRemoteObject的子类,而LocalRemoteObject为RemoteObject 的子类。返回的MyRemote的实例会返回到客户端
-
(6)前台FA调用后台服务函数,显示电量
- 客户端重载IAbilityConnection类的函数 onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode)
(六)测一测
1.Feature Ability、Particle Ability
2.Data Ability、Service Ability
3.View、Controller
4.INITIAL、INACTIVE、ACTIVE、BACKGROUND
5.×
6.deviceID、bundleName、abilityName
7.√
8.√
五、js基础语法
(一)HML语法
1.页面结构
- HML(HarmonyOS Markup Language),类似于HML定义页面元素的方法定义APP页面组成
- JS UI框架处理该代码生成DOM
- 通过DOM,JS能够动态处理HML文件中的内容
- HML-骨架
2.数据绑定
MVVM模式
-
动态数据绑定
{{}}
-
//hml <div> <text> {{content[1]}} </text> </div> //js export default { data: { content: ['Hello World!', 'Welcome to my world!'] } }
-
3.事件绑定
-
通过
on
或者@
绑定在组件上-
//hml <div class="container"> <div class="box"> <input type="button" class="btn" value="increase" onclick="increase" /> </div> </div>
-
4.列表渲染
- 即对一组相同的元素进行显示时使用
- 是通过
for
关键字,三种方法
【第1种】
//array数组定义了几个元素就显示几条信息
<div for="{{array}}" tid="id" onclick="changeText">
<text>{{$idx}}.{{$item.name}}</text>
</div>
【第2种】
//类似于枚举,value in array
<div for="{{value in array}}" tid="id" onclick="changeText">
<text>{{$idx}}.{{value.name}}</text>
</div>
【第3种】
//字典数组(每一个元素都是一个键值堆)
<div for="{{(index, value) in array}}" tid="id" onclick="changeText">
<text>{{index}}.{{value.name}}</text>
</div>
5.条件渲染
- 分为两种
- if/elif/else
- show
- 区别
- 【if/elif/else】,为false时,不会在vdom中构建,也不会渲染
- 【show】,为false时,会在vdom构建,但不会渲染
- 注意:使用【if/elif/else】时,为同级组件,不然编译无法通过
<text if="{{showit}}"> Hello-TV </text>
<text elif="{{display}}"> Hello-Wearable </text>
<text else> Hello-World </text>
(二)CSS语法
1.尺寸单位
- 逻辑像素与物理像素之间的关系
- 逻辑像素px:默认屏幕具有的逻辑宽度为720px(手机屏幕),如100px在实际宽度为1440物理像素的屏幕上,实际渲染为200物理像素
- 百分比:.css文件中通常以%表示,表示该组件占父组件尺寸的百分比
2.样式选择器
- CSS选择器用于选择需要添加样式的元素
- 优先级(会产生覆盖现象):内联样式 > id > class > tag
- 组件样式的生命除了用单独的.css文件外,也可以直接定义在.hml文件中
选择器 | 中文名 | 样例 | 样例描述 |
---|---|---|---|
.class | 类选择器 | .container | 用于选择class="container"的组件 |
#id | ID选择器 | #titleId | 用于选择id="titleId"的组件 |
tag | 标签选择器 | text | 用于选择text组件 |
, | 并集选择器 | .title, .content | 用于选择class="title"和 class="content"的组件 |
.class tag | 后代选择器 | .content text | 选择具有class="content"行为的所有 text组件 |
任何的标签都可以携带id属性和class属性,但id属性只能被某一特定标签引用一次,而class得特点(类选择器可以被多中标签使用;同一个标签可以使用多个类选择器用空格隔开)注意:CSS层尽量用class,ID是JS层用的,再就是一般由ID的元素,我们一般认为有动态效果。即:类上样式、id上行为
3.伪类
- CSS伪类是选择器中的关键字,用于指定要选择元素的特殊状态
- 伪类选择器:CSS允许对于元素的不同状态,定义不同的样式信息,伪类选择器分为(静态伪类-用于超链接、动态伪类-所有标签都适用),对于伪类选择器简单理解就是触发前一个样式,触发后一个样式
名称 | 支持组件 | 描述 |
---|---|---|
:disabled | 支持disabled属性的组件 | 表示disabled属性变为true时的元素 |
:focus | 支持focusable属性的组件 | 表示获取focus时的元素 |
:active | 支持click事件的组件 | 表示被用户激活的元素,如:被用户按下 的按钮、被激活的tab-bar页签 |
:checked | input[type=“checkbox”、 type=“radio”]、 switch | 表示checked属性为true的元素 |
(三)JS语法
1.语法
- this关键字
- 模块声明
- import router from ‘@system.router’;
- 代码引用
- import utils from ‘…/…/common/utils.js’;
2.对象
-
对象分类
-
自定义对象
-
应用对象
- 应用对象,$app
- 属性包括:$def,为Object类型
- 可以使用this.$app.$def获取 在app.js中暴露的对象
-
页面对象
-
对象 类型 描述 data Object/Function 页面的数据模型,类型是对象或者函数,如果类型 是函数,返回值必须是对象 $refs Object 持有注册过ref 属性的DOM元素或子组件实例的对 象 private Object 页面的数据模型,private下的数据属性只能由当前 页面修改 public Object 页面的数据模型,public下的数据属性的行为与 data保持一致 props Array/Object props用于组件之间的通信,props名称必须用小写 computed Object 用于在读取或设置进行预先处理,计算属性的结果 会被缓存
-
-
3.方法
- 数据方法
- set
- delete
方法 | 参数 | 描述 |
---|---|---|
$set | key: string, value: any | 添加新的数据属性或者修改 已有数据属性 |
$delete | key: string | 删除数据属性 |
- 公共方法:$element
- 跟$ref很像,就是用来引用的
(四)测一测
1.√
2.for
3.×
4.$element、$refs
5.class=“.title”、class=“.content”
6.√
7.√
8.$element
(五)说明
- HML是类HTML的标记语言,说类Web开发范式和数据模型,开发者可以通过编写JS、CSS、HTML标签和数据绑定的方式开发UI代码和业务逻辑(也可以算作对)