基本语法

装饰器:如下图@Entry、@Component、@State都是装饰器。

@Component表示自定义组件。@Entry表示该自定义组件的入口组件。@State表示组件中的状态变量,状态变量的变化会触发UI的刷新。UI描述:以声明式的方式来描述UI的结构,如上图build()方法中的代码。自定义组件:可复用的UI组件,如上图被@Component装饰的struct App。属性方法:通过链式调用使用更多属性,如上图.width('100%').height('100%')等。事件方法:通过链式调用使用更多事件逻辑,如上图中的.onClick(()=>{ })等。

@Entry

@Component

struct App {

@State myText: string = 'HarmonyOS4.0';

build() {

Column() {

Text(`${this.myText}`).fontSize(32).fontWeight(800)

Button('点击').onClick(() => {

this.myText = '欢迎使用鸿蒙'

}).width(100).margin({top:20})

}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)

}

}

创建自定义组件

注意:@Entry装饰的组件,其build函数下的根结点必须为容器组件,并且forEach不能作为根节点。     

           @Component装饰的组件,其build函数下的根结点可以为非容器组件,并且forEach不能作为根节点。            

1、在入口组件内部使用自定义组建

@Component

struct ExanpleComponent {

@State textValue: string = '组件状态'

build() {

Text(this.textValue)

.fontSize(32)

.fontWeight(600)

.fontColor('#e33')

.onClick(() => {

this.textValue = '组件状态变化'

})

}

}

@Entry

@Component

struct App {

@State myText: string = 'HarmonyOS4.0';

build() {

Column() {

ExanpleComponent()

Text(`${this.myText}`)

.fontSize(32)

.fontWeight(800)

Button('点击')

.width(100)

.margin({ top: 20 })

.onClick(() => {

this.myText = '欢迎使用鸿蒙'

})

}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)

}

}

2、从外部导入使用自定义组建

Index.ets @Entry入口文件

Example.ets @Component自定义组件文件

生命周期(页面和自定义组件)

1、页面生命周期,即被@Entry修饰的组件生命周期

onPageShow:页面每次显示时触发。onPageHide:页面每次隐藏时触发。onBackPress:当用户点击返回按钮时出发。

2、组件生命周期,即被@Component修饰的组件生命周期

aboutToAppear:组件刚出现的时候回调该接口,具体为在创建自定义组件实例后早build函数前。aboutToDisappear:在自定义组件销毁时执行。

@Styles

注意:@Style不能有参数。

// 定义全局@style样式

@Styles function publicStyle() {

.width('100%')

.height('100%')

.backgroundColor('#3ce')

}

@Entry

@Component

struct App {

@State myText: string = 'HarmonyOS4.0';

// 定义局部@style样式

@Styles internalStyle(){

.width(200)

.margin({ top: 20 })

}

build() {

Column() {

Button(this.myText)

.internalStyle()

.fontSize(20)

.onClick(() => {

this.myText = '欢迎使用鸿蒙'

})

}.publicStyle().justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)

}

}

@Extend

概念

和@Style不同,@Extend仅支持定义在全局,不支持在组件内部定义。和@Style不同,@Extend装饰的方法支持参数,可以在调用时传递参数

// 定义全局@Extend样式

@Extend(Column) function publicStyle(width:string,height:string) {

.width(width)

.height(height)

.backgroundColor('#3ae')

}

@Entry

@Component

struct App {

@State myText: string = 'HarmonyOS4.0';

build() {

Column() {

Button(this.myText)

.fontSize(20)

.onClick(() => {

this.myText = '欢迎使用鸿蒙'

})

}.publicStyle('100%','100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)

}

}

stateStyles多态样式

概述

stateStyles是属性方法,类似于css伪类,ArkUI提供了以下四种状态:

focused:获焦状态normal:正常状态pressed:按压状态disabled:不可用状态

@Styles function focusedStyle() {

.backgroundColor('red')

}

@Entry

@Component

struct App {

@State myText: string = 'HarmonyOS4.0';

@Styles pressedStyle() {

.backgroundColor('green')

}

build() {

Column() {

Button(this.myText)

.fontSize(20)

.stateStyles({

focused: focusedStyle,

pressed: this.pressedStyle,

normal: {

.backgroundColor('blue')

},

})

.onClick(() => {

this.myText = '欢迎使用鸿蒙'

})

}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)

}

}

@State状态管理

概念

状态变量:被@State装饰的变量,状态变量的状态值的改变会引起UI的渲染更新。常规变量:没有被@State装饰的变量,它的改变永远不会引起UI的渲染更新。

@Component

struct MyComponent {

@State count: number = 0;

private increaseBy: number = 1;

build() {

}

}

@Component

struct Parent {

build() {

Column() {

// 从父组件初始化,覆盖本地定义的默认值

MyComponent({ count: 1, increaseBy: 2 })

}

}

}

@Prop父子单项同步(父传子)

概述

单项同步:对父组件的状态变量值的修改,将同步到子元素@Prop装饰的变量,子组件@Prop变量的修改不会同步到父组件的状态变量上。

注意:@props装饰器不能在@Entry装饰的自定义组件中使用。

@Component

struct Child {

@Prop count: number;

build() {

Column() {

Text(`子组件: ${this.count} `)

// @Prop装饰的变量不会同步给父组件

Button(`子组件-1`).onClick(() => {

this.count -= 1;

}).margin({ top: 24 })

}

}

}

@Entry

@Component

struct Parent {

@State num: number = 0;

build() {

Column() {

Text(`父组件:${this.num}`)

// 父组件的修改会同步给子组件

Button(`父组件+1`).onClick(() => {

this.num += 1;

}).margin({ top: 24 })

// 子组件

Child({ count: this.num }).margin({ top: 24 })

}.width('100%').justifyContent(FlexAlign.Center).margin({ top: 24 })

}

}

@Link父子双向同步(父传子、子传父)

概述

双向同步:对父组件的状态变量值的修改,将同步到子元素@Link装饰的变量,子组件@Link变量也将同步到父组件的状态变量上。

注意:@Link装饰器不能在@Entry装饰的自定义组件中使用。

@Component

struct Child {

@Link items: number[];

build() {

Column() {

Button(`子元素修改数组`).onClick(() => {

this.items = [100, 200, 300];

})

ForEach(this.items, item => {

Text(`${item}`)

})

}

}

}

@Entry

@Component

struct Parent {

@State arr: number[] = [1, 2, 3];

build() {

Column() {

Button(`父元素修改数组`).onClick(() => {

this.arr = [5, 6, 7];

})

ForEach(this.arr,

item => {

Text(`${item}`)

}

)

Child({ items: $arr })

}

}

}

@Provide和@Consume后代组件双向同步(跨组建传参)

概述

双向同步:@Provide与@Consume,应用于后代组件的数据双向同步,应用于数据在多个层级之间传递,实现跨层级传递。介绍:@Provide装饰的变量是在祖先节点中,是变量的提供者,@Consume装饰的变量是在后代组件中,是变量的消费者。

注意:@Provide与@Consume装饰的变量必须通过相同的属性名进行同步数据。

@Component

struct CompD {

// @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量

@Consume publicValue: number;

build() {

Column() {

Text(`D组件${this.publicValue}`)

Button(`D组件按钮-1`)

.onClick(() => this.publicValue -= 1)

}

.width('50%')

}

}

@Component

struct CompC {

build() {

CompD()

}

}

@Component

struct CompB {

build() {

CompC()

}

}

@Entry

@Component

struct CompA {

// @Provide装饰的变量publicValue由入口组件CompA提供其后代组件

@Provide publicValue: number = 0;

build() {

Column() {

Text(`A组件${this.publicValue}`)

Button(`A组件按钮+1`)

.onClick(() => this.publicValue += 1)

CompB()

}

}

}

@Observed和@ObjectLink多层嵌套双向同步

概述

上文所述的装饰器只能观察到一层的变化,对于多层嵌套的情况,比如二维数组、多维对象,它们其他层级的变化是无法被观察的,因此引出了@Observed和@ObjectLink装饰器。

注意:

@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。@ObjectLink装饰的变量不能被赋值。

// 开发进行中...

@Watch监听状态的变化

概述

LocalStorage是页面级的UI存储,通过@Entry装饰器接收的参数可以在页面内共享一个LocalStorage实例。

@Entry

@Component

struct CompA {

@Watch('change') @State count: number = 1

change() {

console.log(`状态变化${this.count}`)

}

build() {

Column() {

Button(`点击状态变化${this.count}`)

.onClick(() => {

this.count++

})

}

}

}

LocalStorage页面级UI状态存储

概述

LocalStorage是页面级的UI存储,通过@Entry装饰器接收的参数可以在页面内共享一个LocalStorage实例。被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件都将获取对该LocalStorage实例的访问权限,一个LocalStorage实例在组建数上可以分配给多个组件。被@Component装饰的组件最多可访问一个LocalStorage实例和AppStorage。LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:

 @LocalStorageProp:@LocalStorageProp装饰的变量与LocalStorage中给予属性建立的是单向同步关系。 @LocalStorageLink:@LocalStorageLink装饰的变量与LocalStorage中给予属性建立的是双向向同步关系。

注意:LocalStorage创建后,命名属性的类型不可更改

1、@LocalStorageProp —— 单项数据同步

// import { Child } from '../components/Example'

let storage = new LocalStorage({ 'PropA': 47 });

@Component

struct Child {

@LocalStorageProp('PropA') num2: number = 1;

build() {

// 点击后,只改变当前组件显示的num2,不会同步到LocalStorage中

Button(`子组件${this.num2}`)

.onClick(() => {

this.num2 += 1;

})

}

}

@Entry(storage)

@Component

struct CompA {

@LocalStorageProp('PropA') num1: number = 1;

build() {

Column({ space: 15 }) {

Child()

// 点击后,只改变当前组件显示的num1,不会同步到LocalStorage中

Button(`父组件 ${this.num1}`)

.onClick(() => this.num1 += 1)

}

}

}

2、@LocalStorageLink  —— 双项数据同步

// import { Child } from '../components/Example'

let storage = new LocalStorage({ 'PropA': 47 });

@Component

struct Child {

@LocalStorageLink('PropA') num2: number = 1;

build() {

Button(`子组件${this.num2}`)

.onClick(() => {

this.num2 += 1;

})

}

}

@Entry(storage)

@Component

struct CompA {

@LocalStorageLink('PropA') num1: number = 1;

build() {

Column({ space: 15 }) {

Child()

Button(`父组件 ${this.num1}`)

.onClick(() => this.num1 += 1)

}

}

}

AppStorage全局UI状态存储

概述

AppStorage是应用全局的状态存储,和LocalStorage不同的是LocalStorage是页面级的,用于页面内的数据共享,而AppStorage是应用于全局状态的共享。AppStorage中也提供了两种同步类型:

@StorageProp:@StorageProp(key)是和AppStorage中key对应的属性建立单向数据同步。@StorageLink:@StorageLink(key)是和AppStorage中key对应的属性建立双向数据同步。

1、@StorageProp —— 单项数据同步

AppStorage.SetOrCreate('PropA', 47);

@Component

struct Child {

@StorageProp('PropA') num2: number = 1;

build() {

Button(`子组件${this.num2}`)

.onClick(() => {

this.num2 += 1;

})

}

}

@Entry()

@Component

struct CompA {

@StorageProp('PropA') num1: number = 1;

build() {

Column({ space: 20 }) {

Child()

Button(`AppStorage ${this.num1}`)

.onClick(() => this.num1 += 1)

}

}

}

2、@StorageLink  —— 双项数据同步

AppStorage.SetOrCreate('PropA', 47);

@Entry()

@Component

struct CompA {

@StorageLink('PropA') storLink: number = 1;

build() {

Column({ space: 20 }) {

Button(`AppStorage ${this.storLink}`)

.onClick(() => this.storLink += 1)

}

}

}

总结:LocalStorage和AppStorage都是运行时内存的状态存储。

PersistentStorage持久化UI状态存储

概述

LocalStorage和AppStorage都是运行时的内存,在应用退出再次启动后,依然能保存选定的结果,这就需要用到PersistentStorage。PersistentStorage将选定的AppStorage属性保留在设备磁盘上。

PersistentStorage.PersistProp('aProp', 47);

@Entry

@Component

struct Index {

@StorageLink('aProp') num: number = 48

build() {

Row() {

Column() {

// 应用退出时会保存当前结果。重新启动后,会显示上一次的保存结果

Button(`${this.num}`)

.onClick(() => {

this.num += 1;

})

}

}

}

}

if/else

概述

条件渲染使用if/else渲染对应状态下的ui内容。鸿蒙开发推荐使用if/else,不推荐使用switch。

ForEach

概述

循环渲染,需要与容器组件配合使用。

@Entry

@Component

struct Parent {

@State simpleList: Array = ['one', 'two', 'three'];

build() {

Row() {

Column() {

ForEach(this.simpleList, // 数据源

(item: string) => {

Text(item).fontSize(32) // 组件生成函数

},

(item: string) => item // 键值生成函数:为数据源arr的每个数组项生成唯一且持久的键值。

)

}

}

}

}

LazyForEach

概述

LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当在滚动容器中使用了LazyForEach,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会进行组件销毁回收以降低内存占用。LazyForEach必须在容器组件内使用,目前仅有List、Grid以及Swiper组件支持数据懒加载,其他组件仍然是一次性加载所有的数据。LazyForEach在每次迭代中,必须创建且只允许创建一个子组件。

class BasicDataSource implements IDataSource {

private listeners: DataChangeListener[] = []

public totalCount(): number {

return 0

}

public getData(index: number): any {

return undefined

}

registerDataChangeListener(listener: DataChangeListener): void {

if (this.listeners.indexOf(listener) < 0) {

console.info('add listener')

this.listeners.push(listener)

}

}

unregisterDataChangeListener(listener: DataChangeListener): void {

const pos = this.listeners.indexOf(listener);

if (pos >= 0) {

console.info('remove listener')

this.listeners.splice(pos, 1)

}

}

notifyDataReload(): void {

this.listeners.forEach(listener => {

listener.onDataReloaded()

})

}

notifyDataAdd(index: number): void {

this.listeners.forEach(listener => {

listener.onDataAdd(index)

})

}

notifyDataChange(index: number): void {

this.listeners.forEach(listener => {

listener.onDataChange(index)

})

}

notifyDataDelete(index: number): void {

this.listeners.forEach(listener => {

listener.onDataDelete(index)

})

}

notifyDataMove(from: number, to: number): void {

this.listeners.forEach(listener => {

listener.onDataMove(from, to)

})

}

}

class MyDataSource extends BasicDataSource {

// 初始化数据列表

private dataArray: string[] = ['demo1', 'demo2', 'demo3', 'demo4']

public totalCount(): number {

return this.dataArray.length

}

public getData(index: number): any {

return this.dataArray[index]

}

public addData(index: number, data: string): void {

this.dataArray.splice(index, 0, data)

this.notifyDataAdd(index)

}

public pushData(data: string): void {

this.dataArray.push(data)

this.notifyDataAdd(this.dataArray.length - 1)

}

}

@Entry

@Component

struct MyComponent {

private data: MyDataSource = new MyDataSource()

build() {

List({ space: 3 }) {

LazyForEach(this.data, (item: string) => {

ListItem() {

Row() {

Text(item).fontSize(20).margin({ left: 10 })

}.margin({ left: 10, right: 10 })

}

.onClick(() => {

// 每点击一次列表项,数据增加一项

this.data.pushData(`demoVale:${this.data.totalCount()}`)

})

}, item => item)

}.backgroundColor('red')

}

}

应用/组件配置

概述

应用图标、应用标签和入口图标、入口标签的配置,分别对应app.json5配置文件和module.json5配置文件文件中的icon和label标签。应用图标和标签是在设置应用中使用,例如设置应用中的应用列表。入口图标是应用安装完成后在设备桌面上中使用。

1、应用配置

2、入口配置

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: