简介
官方的解释
UI框架
HarmonyOS提供了一套UI开发框架,即方舟开发框架(ArkUI框架)。方舟开发框架可为开发者提供应用UI开发所必需的能力,比如多种组件、布局计算、动画能力、UI交互、绘制等。
方舟开发框架针对不同目的和技术背景的开发者提供了两种开发范式,分别是基于ArkTS的声明式开发范式(简称“声明式开发范式”)和兼容JS的类Web开发范式(简称“类Web开发范式”)。以下是两种开发范式的简单对比。
ArkTS是一种为构建高性能应用而设计的编程语言。ArkTS在继承TypeScript语法的基础上进行了优化,以提供更高的性能和开发效率。
项目结构
entry:HarmonyOS工程模块,编译构建生成一个HAP包。
src > main > ets:用于存放ArkTS源码。
src > main > ets > entryability:应用/服务的入口。
src > main > ets > entrybackupability:应用提供扩展的备份恢复能力。
src > main > ets > pages:应用/服务包含的页面。
src > main > resources:用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。关于资源文件,详见资源分类与访问。
src > main > module.json5:模块配置文件。主要包含HAP包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。具体的配置文件说明,详见module.json5配置文件。
build-profile.json5:当前的模块信息 、编译信息配置项,包括buildOption、targets配置等。
hvigorfile.ts:模块级编译构建任务脚本。
obfuscation-rules.txt:混淆规则文件。混淆开启后,在使用Release模式进行编译时,会对代码进行编译、混淆及压缩处理,保护代码资产。详见开启代码混淆。
oh-package.json5:用来描述包名、版本、入口文件(类型声明文件)和依赖项等信息。
oh_modules:用于存放三方库依赖信息。
build-profile.json5:工程级配置信息,包括签名signingConfigs、产品配置products等。其中products中可配置当前运行环境,默认为HarmonyOS。
hvigorfile.ts:工程级编译构建任务脚本。
oh-package.json5:主要用来描述全局配置,如:依赖覆盖(overrides)、依赖关系重写(overrideDependencyMap)和参数化配置(parameterFile)等。
基本组件
按钮
Button() {
Text('Next')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('40%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
console.info(`Succeeded in clicking the 'Next' button.`)
// 跳转到第二页
router.pushUrl({ url: 'pages/Second' }).then(() => {
console.info('Succeeded in jumping to the second page.')
}).catch((err: BusinessError) => {
console.error(`Failed to jump to the second page. Code is ${err.code}, message is ${err.message}`)
})
})
arkts
装饰器
@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()) } } }
@Builder装饰器:自定义构建函数
装饰器:用于装饰类、结构、方法以及变量,并赋予特殊含义。如上述的代码片段中@Entry/@Component/@State都属于装饰器,@表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,类似于赋予变量响应式,状态变量值发生变化会触发组件更新。
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的参数。
所有声明在build()函数的语句,我们统称为UI描述,UI描述需要遵循以下规则:
@builder
//在组件外定义words构建函数 @Entry @Component struct Index { @State message: string = '@Builder \n 组件内构建函数' //设置状态变量,方便在选中诗词时能够作为标志位,默认未选中 @State isChoose: boolean = false // 这个是用来创建一个容器的 用来创建组件更好 @Builder words(content:string){ Row(){ Image(this.isChoose ? $r('app.media.foreground') : $r('app.media.startIcon')) .width(35) .margin(15) //构建函数调用自己的形式参数时不需要使用this引用 Text(content) .fontSize(25) .decoration({type:this.isChoose ? TextDecorationType.LineThrough : TextDecorationType.None}) } .backgroundColor(Color.Orange) .padding(5) .borderRadius(25) .width('85%') .height(70) .margin({ top:10 }) //给row组件加上点击事件 .onClick(()=>{ this.isChoose = !this.isChoose }) } build() { Row() { Column({space:20}) { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .textAlign(TextAlign.Center) //设置文本居中显示 //在组件内调用组件内定义的构建函数:由于该构建函数属于组件内的一部分,因此需要使用this进行调用 this.words('是造物者之无尽藏也,') this.words('而吾与子之所共适!') //调用组件外构建函数 // words2('是造物者之无尽藏也,') // words2('而吾与子之所共适!') } .width('100%') } .height('100%') } } let isChoose = false //创建组件外构建函数:必须加上关键字function @Builder function words2(content:string){ Row(){ Image(isChoose ? $r('app.media.layered_image') : $r('app.media.background')) .width(35) .margin(15) //构建函数调用自己的形式参数时不需要使用this引用 Text(content) .fontSize(25) .decoration({type:isChoose ? TextDecorationType.LineThrough : TextDecorationType.None}) } .backgroundColor(Color.Pink) .padding(5) .borderRadius(25) .width('85%') .height(70) .margin({ top:10 }) //给row组件加上点击事件 .onClick(()=>{ isChoose = !isChoose }) }
自定义组件
创建一个 component 文件 下面 放组件
@Component export struct MyButton { @State count: number = 0; @State btnName: string = 'click me' build() { Column() { // text 只能 放 string 类型 Text(''+this.count) Divider() // 直接使用便可以了 Button(this.btnName) .onClick(() => { this.count += 1; }) } .width("100%") .height("100%") } }
引用和 使用 像vue 一样
// 可以直接使用名字,会自动引用 import { MyButton } from '../Component/MyButton'; @Entry @Component struct Index { @State message: string = 'Hello World' build() { Column(){ Text("this is father") MyButton({ //里面 定义的变量名 加上 就可以了 btnName:'father button' }) }.height('100%') .width('100%') } }
生命周期
onCreate
如用户打开电池管理应用,在应用加载的过程中,在UI界面出现之前,可以在onCreate回调中读取; 在Create状态,在UIAbility实例创建时触发,系统会调用onCreate回调。
在onWindowStageCreate(windowStage)中通过loadContent接口设置应用要加载的页面。
在UIAbility的UI页面完全不可见之后,即UIAbility切换⾄后台时候触发;
当地图应用切换到后台状态,可以在onBackground回调中停止定位功能,以节省系统的资源消耗;
可以在onBackground回调中释放UI页面不可见时无用的资源,或者在此回调中执行较为耗时的操作。
路由
简单的跳转
// Index.ets // 导入页面路由模块 import { router } from '@kit.ArkUI'; @Entry @Component struct Index { @State message: string = 'Hello World' build() { Column(){ Text("this is father") Button('跳转').onClick(()=>{ router.pushUrl({ url:'pages/Demo' // params:{ // id:'index', // data:10 // } }).then(()=>{ console.log( "成功"); }) }) }.height('100%') .width('100%') } }
@Entry @Component struct Demo { build() { Column(){ Text("this is child") }.height('100%') .width('100%') } }
管理路由的页面
跳转加参数
// Index.ets // 导入页面路由模块 import { router } from '@kit.ArkUI'; @Entry @Component struct Index { @State message: string = 'Hello World' build() { Column(){ Text("this is father") Button('跳转').onClick(()=>{ router.pushUrl({ url:'pages/Demo', params:{ id:'index', data:10 } }).then(()=>{ console.log( "成功"); }) }) }.height('100%') .width('100%') } }
import { router } from '@kit.ArkUI'; // 定义参数的结构 interface ParamsFromIndex { index?: string; // 假设 index 是一个可选的字符串 id?: string; // 其他参数可以在这里添加 } @Entry @Component struct Demo { @State message: string = "second page"; @State paramsFromIndex: ParamsFromIndex = router.getParams() as ParamsFromIndex; // 明确类型 build() { Column() { Button('click me').onClick(() => { console.log(this.paramsFromIndex.id); // 访问 index }); }.height('100%') .width('100%'); } }
函数
基本使用通过
function print(name?: string) { if (name == undefined) { console.log('Hello!'); } else { console.log(`Hello, ${name}!`); } } Button("click me").onClick(()=>{ print("youren") })
function sum(...numbers: number[]): number { let res = 0; for (let n of numbers) res += n; return res; } Button("click me").onClick(()=>{ let a = sum(1, 2, 3) // 返回6 console.log(''+a) })
function foo(x: number): void; /* 第一个函数定义 */ function foo(x: string): void; /* 第二个函数定义 */ function foo(x: number | string): void { /* 函数实现 */ } foo(123); // OK,使用第一个定义 foo('aa'); // OK,使用第二个定义
类
class Person { name: string = '' surname: string = '' constructor (n: string, sn: string) { this.name = n; this.surname = sn; } fullName(): string { return this.name + ' ' + this.surname; } } let p = new Person('John', 'Smith'); console.log(p.fullName());