ArkUI
# 两种开发范式
基于ArkTS的声明式开发范式(简称“声明式开发范式”)和兼容JS的类Web开发范式(简称“类Web开发范式”)
# ArkTS在ts的基础上主要扩展了三种能力
基本语法:ArkTS定义了声明式UI描述,自定义组件和动态扩展UI元素的能力,再配合ArkUI开发框架的系统组件以及相关的事件方法,属性方法等共同构成了UI开发的主题。
状态管理:ArkTS 提供了多维的状态管理机制。在UI开发框架中,与UI相关的数据可以在组件内使用,也可以在不同组件层级间传递,比如:父子组件之间,爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。从数据传递形式来看,分为只读单项传递和可变更双向传递。
渲染控制:ArkTS提供了渲染控制的能力。条件渲染可根据应用的不同状态,渲染对应状态的UI内容。渲染内容可以从数据源的迭代获取数据,并在每次迭代过程中创建相应的组件。数据懒加载从数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。

# 基本语法

ArkTS 声明式开发范式:
- 装饰器:用来装饰类、结构体、方法和变量、赋予其特殊含义。比如@Entry、@Component、@State 都是装饰器。@Component是自定义组件,@Entry是入口组件,@State是状态变量,此状态变化会引起ui变更
- 自定义组件:可复用的ui组件,可组合其他组件
- UI描述:声明式的方式来描述UI的结构,如上述 build() 方法内部的代码块。
- 内置组件:框架中默认内置的基础和布局组件。
- 事件方法:用于添加组件对事件的响应逻辑,统一通过事件方法来进行设置。比如onClick
- 属性方法:用于组件属性的配置,统一通过属性方法进行设置,如fontSize()、width()、height()、color() 等,可通过链式调用的方式设置多项属性。
- build方法内可以容纳内置组件和其他自定义组件。
# 扩展语法:
# @Builder/@BuilderParam
特殊的封装UI描述的方法,细粒度的封装和复用UI描述。
@Builder: 自定义构建函数:
- 将重复使用的UI元素抽象成一个方法,并在build方法中调用
- 使用范围:组件范围、全局范围使用
- 组件内定义:
@Entry @Component struct Index { // 组件内 @Builder MuCOm() { Row() { Text('111') } } build() { Column() { this.MuCOm() MuGlobalCOm() } } } // 全局 全局声明需要加function关键字,使用时直接写函数名称 @Builder function MuGlobalCOm() { Row() { Text('global') } }@BuilderParam: 装饰器,用于声明任意UI描述的一个元素,类似于vue里的solt 占位符和React中的children
- 类似于插槽,@BuilderParam 装饰的方式 只能被@Builder初始化
- 尾随闭包
import ListMap from '../view/ListMap' @Entry @Component struct Home { build() { // MuGlobalCOm() Column({ space: 20}) { ListMap({title:"音乐"}) { Text('11') } ListMap({title:"书法"}) { Text('22') } ListMap({title:"美术"}) } } } @Component struct ListMap { @Prop title: string; @BuilderParam ListContent: () => void = this.defaultContent; @Builder defaultContent () { Text('默认展示的内容') } build() { Column() { Text(this.title) .width('100%') .height(100) .textAlign(TextAlign.End) this.ListContent() } .width('100%') .height('100vh') .backgroundColor(Color.Gray) } } export default ListMap;
具名插槽
import ListMap from '../view/ListMap' import ListModel from '../view/ListModel' @Entry @Component struct Home { @Builder ListHeader() { Text('header') } @Builder ListFooter() { Text('footer') } build() { Column({ space: 20}) { ListModel({ listHeader: this.ListHeader, listFooter: this.ListFooter, }) } } } @Component struct ListModel { @BuilderParam listHeader: () => void = this.defaultHeader @BuilderParam listFooter: () => void = this.defaultFooter @Builder defaultHeader() { Text('111') } @Builder defaultFooter() { Text('footer') } build() { Column() { this.listHeader() Text('content') this.listFooter() } } } export default ListModel
# @Extend/@Styles: 扩展内置组件和封装属性样式,更灵活组合内置组件。
- 和@Styles不同,@Extend支持封装指定组件的私有属性、私有事件和自身定义的全局方法
- 和@Styles不同,@Extend 装修的方法支持参数
- @Extend装饰的方法参数可以为function,作为Event事件的句柄
- @Extend的参数可以为状态变量,当状态变量改变时,UI可以正常的被刷新渲染
- @Extend: 扩展组件的样式、事件,实现复用效果
- @Extend仅支持在全局定义,不支持在组件内部定义。
- 语法:
@Extend(组件名)
function ExtendName(参数1....) {
.属性()
.事件(()=>{})
}
// 使用
组件(){}
.ExtendName(参数1...)
示例:
import { promptAction } from '@kit.ArkUI'
@Entry
@Component
struct ExtendUI {
build() {
Column({ space: 20 }) {
Button('hello World')
.myBtn(ButtonType.Capsule)
Button('hello World')
.myBtn(ButtonType.Circle)
.width(100)
Button('hello World')
.myBtn(ButtonType.Normal)
.width(100)
}
}
}
@Extend(Button)
function myBtn(type: ButtonType){
.fontColor(Color.Blue)
.type(type)
.fontWeight(700)
.onClick(() => {
promptAction.showToast({
message: `ButtonType: ${type}`,
bottom: 300
})
})
}
@Style: 提取通用的事件和属性,支持全局和组件内
语法:
// 组件内
@Styles setStyle() {
.通用属性()
.通用事件(()=>{})
}
// 全局
@Styles
function commonStyle() {
.通用属性()
.通用事件(()=>{})
}
示例:
import { promptAction } from '@kit.ArkUI'
@Entry
@Component
struct StyleUI {
@Styles setColor() {
.backgroundColor(Color.Black)
.width(200)
.height(100)
.borderRadius(10)
}
build() {
Column({ space: 20 }) {
Row() {
Text('test @Style')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.width('100%')
}
.setColor()
}
.setSte()
}
}
@Styles
function setSte() {
.backgroundColor(Color.Gray)
}
# stateStyles:多态样式,可以依据组件的内部状态的不同,设置不同样式。
- stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下五种状态:
- focused:获焦态
- normal:正常态
- pressed:按压态
- disabled:不可用态
- selected10+:选中态
示例
Button('aaa')
.stateStyles({
pressed: {
.backgroundColor('#ff707070')
.width(200)
},
})
# 基础组件-ArkUI

# image 组件
加载网络图片,注意需要开启网络权限,预览不限制,真机或者模拟器运行需要申请网络权限 需要在module.json5 配置requestPermissions
requestPermissions: [{"name" : "ohos.permission.INTERNET"}],
加载本地图片 $r
import router from '@ohos.router'
@Component
@Entry
struct Index {
build() {
Column(){
Image($r('app.media.app_icon'))
}
.width('100%')
.height('100%')
.backgroundColor('#f5f5f5')
}
}
提示
鸿蒙开发遵循一个原则:一个页面或者自己封装的组件 必须有且只有一个根组件
# 堆叠组件
把一个组件堆叠到另外一个组件上的效果,称为层叠效果或者堆叠效果。 使用语法:
Stack() {
item1()
item2()
item3()
}
默认情况下,最后的组件越叠在最上面, 子组件都在Stack容器内居中堆叠: Alignment.Center,如果需要指定谁在最上层,可以通过zIndex ,越大越在上面

# 自定义组件:
语法:
@Component
struct MyComponent {
build() {
}
}
基本结构:
- struct:自定义组件基于struct实现,struct + 自定义组件名 + {} 的组合构成自定义组件,不能有继承关系。
- @Component:@Component 装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述ui,一个struct只能被一个@Component装饰。
- build()函数:build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数
build函数注意事项
- 不允许声明本地变量
build() {
// 反例:不允许声明本地变量
let a: number = 1; // error
}
- 不允许在UI描述里直接使用console.info,但允许在方法或者函数里使用
build() {
console.log('test') // error
}
- 不允许创建本地的作用域
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('...')
}
}
# @LocalBuilder装饰器:维持组件父子关系
# 语法:
@LocalBuilder MyBuilderFunction() { ... }
# 限制条件:
- @LocalBuilder 只能在所属组件内声明,不允许全局声明
- @LocalBuilder 不能被内置装饰器和自定义装饰器使用
- 自定义组件内的静态方法不能和@LocalBuilder 一起使用
# @LocalBuilder 和局部@Builder 使用区别
@Builder方式引用传参时,为了改变this指向,使用bind(this)后,会导致组件的父子关系和状态管理的父子关系不一致,但是@LocalBuilder是否使用bind(this), 都不会改变组件的父子关系
# 参数传递规则
@LocalBuilder 函数的参数传递有按值传递和按引用传递两种,均需遵守一下规则:
- 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
- 在@LocalBuilder修饰的函数内部,不允许改变参数值
- 只有传入一个参数,且参数需要直接传入对象字面量才会按引用传递该参数,其余传递方式均为按值传递
# 按引用传递参数
按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@LocalBuilder方法内的UI刷新。
若子组件调用父组件的@LocalBuilder函数,传入的参数发生变化,不会引起@LocalBuilder方法内的UI刷新
按引用传递参数时,如果在@LocalBuilder方法内调用自定义组件,ArkUI 提供$$作为按引用传递参数的范式
class ReferenceType {
paramString: string = '';
}
@Component
struct HelloComponent {
@Prop message: string;
build() {
Row() {
Text(`HelloComponent===${this.message}`);
}
}
}
@Entry
@Component
struct Parent {
@State variableValue: string = 'Hello World';
@LocalBuilder
citeLocalBuilder($$: ReferenceType) {
Row() {
Column() {
Text(`citeLocalBuilder===${$$.paramString}`);
HelloComponent({ message: $$.paramString });
}
}
}
build() {
Column() {
this.citeLocalBuilder({ paramString: this.variableValue });
Button('Click me').onClick(() => {
this.variableValue = 'Hi World';
})
}
}
}
# 按值传递参数
调用@LocalBuilder 装饰的函数默认按值传递,当传递的参数为状态变量时,状态变量的改变不会引起@LocalBuilder方法内的UI刷新,所以当使用状态变量是,推荐使用按引用传递
# @LocalBuilder和@Builder区别说明
函数componentBuilder被@Builder修饰时,显示效果是 “Child”,函数componentBuilder被@LocalBuilder修饰时,显示效果是“Parent”。
提示
@Builder componentBuilder()通过this.componentBuilder的形式传给子组件@BuilderParam customBuilderParam,this指向在Child的label,即“Child”。
@LocalBuilder componentBuilder()通过this.componentBuilder的形式传给子组件@BuilderParam customBuilderParam,this指向Parent的label,即“Parent”。
# 使用场景
@LocalBuilder在@ComponentV2修饰的自定义组件中使用
使用局部的@LocalBuilder在@ComponentV2修饰的自定义组件中调用,修改变量触发UI刷新