前言
在线JSON转TypeScript接口工具 - 类型定义生成
文档中心-HarmonyOS NEXT开发文档-华为开发者联盟
一. 基本语法概述
1. @Entry、@Component和@State都是装饰器,@Component表示自定义组件,@Entry表示该自定义组件为入口组件,@State表示组件中的状态变量,状态变量变化会触发UI刷新,而struct 不是装饰器,是关键字,用来定义组件
2.页面和自定义组件生命周期
- aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
- onPageShow:页面每次显示时触发。
- onPageHide:页面每次隐藏时触发一次。
- aboutToDisappear:在自定义组件即将析构销毁时执行。
- onBackPress:当用户点击返回按钮时触发。
(1).A页面初次加载---aboutToApper()--->build()--->onPageShow()
(2).A页面跳转到B页面---B.aboutToApper()--->B.build()--->A.onPageHide()--->B.onPageShow()
(2).B页面按返回键到A页面---B.onBackPress()--->B.onPageHide()--->A.onPageShow--->B.aboutToDisapper()
3.@Builder装饰器:自定义构建函数
-
组件内自定义构建函数(无function声明) @Builder MyBuilderFunction(){ ... } 使用方法:this.MyBuilderFunction(){ ... }
-
全局自定义构建函数(有function声明) @Builder function MyGlobalBuilderFunction(){ ... } 使用方法:MyGlobalBuilderFunction()
4.@BuilderParam装饰器:引用@Builder函数
- 初始化@BuilderParam装饰的方法 注意:@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。
@Component
struct Child {
@BuilderParam aBuilder0: () => void = this.doNothingBuilder
build(){}
}
- 用父组件自定义构建函数初始化子组件@BuilderParam装饰的方法
@Component
struct Child {
@BuilderParam aBuilder0: () => void;
build() {
Column() {
this.aBuilder0()
}
}
}
5.鸿蒙中使用interface - 定义纯数据类型(而不是使用java的Class类)
// interface - 纯数据类型定义(推荐)
export interface BannerDataModelData {
desc: string;
id: number;
imagePath: string;
isVisible: number;
order: number;
title: string;
type: number;
url: string;
}
// class - 包含逻辑(不推荐用于纯数据)
export class BannerDataModelData {
desc: string;
id: number;
// ...其他字段
// 可能包含不必要的方法
validate(): boolean {
return this.id > 0;
}
}
6.ArkTS中单例模式的优雅实现方式.(特别适合管理应用级的配置数据和共享状态)
-
let mainViewModel = new MainViewModel();
-
export default mainViewModel as MainViewModel;
// 这种写法的核心优势:
// ArkTS的这种写法优势:
// 更简洁:不需要私有构造函数和getInstance方法
// 模块化:利用ES6模块系统的单例特性
// 自动初始化:在模块加载时自动创建实例
//
// ✅ 简单高效:利用模块系统天然的单例特性
// ✅ 性能优化:避免重复创建相同的配置数据
// ✅ 维护性:集中管理tab配置,一处修改全局生效
// ✅ HarmonyOS最佳实践:符合官方推荐的数据共享模式
export class MainViewModel {
/**
* 首页底部Tab显示数据
*/
tabTitle: Array<TabItem> = [
{
index: 0,
title: "首页",
imageActivated: $r('app.media.icon_sel_home'),
imageOriginal: $r('app.media.icon_unsel_home')
},
{
index: 1,
title: "发现",
imageActivated: $r('app.media.icon_sel_find'),
imageOriginal: $r('app.media.icon_unsel_find')
},
{
index: 2,
title: "热门",
imageActivated: $r('app.media.icon_sel_hot'),
imageOriginal: $r('app.media.icon_unsel_hot')
},
{
index: 3,
title: "我的",
imageActivated: $r('app.media.icon_sel_mine'),
imageOriginal: $r('app.media.icon_unsel_mine')
}
]
}
let mainViewModel = new MainViewModel();
export default mainViewModel as MainViewModel;
7.使用vp自适应间距,使用fp自适应字体.
Column() {
Image(item.index ==index? item.imageActivated:item.imageOriginal)
.width("21vp").height("21vp")
Text(item.title).fontSize("10fp")
.margin("5vp")
}
.width("100%").height("100%")
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
8. $$ 的作用原理
$$组件参数中使用$$this.isRefreshing时,ArkUI 框架会自动将@State变量转化为双向绑定.
9. Array= []等价于 HomeModelIssueListItemList[]=[]
10.if(showLoadingState!==false){}和if(showLoadingState){}的区别
(1).if(showLoadingState!==false)
showLoadingState | !== false | if (showLoadingState) |
|---|---|---|
true | ✅ 执行 | ✅ 执行 |
false | ❌ 不执行 | ❌ 不执行 |
undefined | ✅ 执行 | ❌ 不执行 |
null | ✅ 执行 | ❌ 不执行 |
0 | ✅ 执行 | ❌ 不执行 |
"" (空字符串) | ✅ 执行 | ❌ 不执行 |
NaN | ✅ 执行 | ❌ 不执行 |
{} (空对象) | ✅ 执行 | ✅ 执行 |
[] (空数组) | ✅ 执行 | ✅ 执行 |
(2).if(showLoadingState){}
showLoadingState 的值 | if (showLoadingState) 结果 | 说明 |
|---|---|---|
true | ✅ 执行 | 布尔真值 |
false | ❌ 不执行 | 布尔假值 |
0 | ❌ 不执行 | 数字零视为假 |
1 | ✅ 执行 | 非零数字视为真 |
"" (空字符串) | ❌ 不执行 | 空字符串视为假 |
"hello" | ✅ 执行 | 非空字符串视为真 |
null | ❌ 不执行 | null 视为假 |
undefined | ❌ 不执行 | undefined 视为假 |
{} (空对象) | ✅ 执行 | 任何对象(包括空对象)都视为真 |
[] (空数组) | ✅ 执行 | 任何数组都视为真 |
11.!==,===和 !=,==的区别
| 运算符 | 行为 | 推荐场景 |
|---|---|---|
!== / === | 严格相等,不转换类型 | 推荐,尤其在判断 0、false、null、undefined 等值时更安全 |
!= / == | 宽松相等,会隐式类型转换 | 不推荐,容易产生意料之外的结果(如 "0" == 0 为 true) |
let errorCode = "0"; // 字符串
if (errorCode !== 0) {
// ✅ 会进入这里,因为 "0" !== 0 类型不同
}
if (errorCode != 0) {
// ❌ 不会进入这里,因为 "0" == 0 会先将字符串转为数字,相等
}
12.export default useRequestStatus 或者 export { useRequestStatus };
| 默认导出 | export default useRequestStatus; | import anyName from './module' |
|---|---|---|
| 命名导出 | export { useRequestStatus }; | import { useRequestStatus } from './module' |
- 默认导出
function useRequestStatus(stateCallback?: (state: string) => void, checkResult: boolean = false): LoadStateResult {
return {
promise: (requestPromise, showLoadingState) => run(requestPromise, checkResult, showLoadingState, stateCallback)
};
}
export default useRequestStatus;
- 命名导出
function useRequestStatus(stateCallback?: (state: string) => void, checkResult: boolean = false): LoadStateResult {
return {
promise: (requestPromise, showLoadingState) => run(requestPromise, checkResult, showLoadingState, stateCallback)
};
}
export { useRequestStatus}
或者直接给function 加上 export修饰符
export function useRequestStatus(stateCallback?: (state: string) => void, checkResult: boolean = false): LoadStateResult {
return {
promise: (requestPromise, showLoadingState) => run(requestPromise, checkResult, showLoadingState, stateCallback)
};
}
二.状态管理V1
- @State装饰器 使变量拥有状态属性的装饰器
- @Prop装饰器:装饰的变量可以和父组件建立单向的同步关系,父组件变化会自动同步到子组件,子组件对变量的修改不会自动传递到父组件。
- @Link装饰器:父子双向同步
- @Provide装饰器和@Consume装饰器:与后代组件双向同步(一对多关系)
- @Watch装饰器 :为状态变量设置回调函数 (无法实现对对象、数组中某一单个属性或数组项变化的监听)
- @Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化(解决状态失效的问题)
tip:状态管理V1存在多种可接受外部传入的装饰器:@State@Prop@Link@ObjectLink (子组件参数)
三.状态管理V2
- @Local装饰器:组件内部状态 (无法确保@State装饰变量的初始值一定为组件内部定义的值)
- @Param: 组件外部输入。(子组件接收参数)
- @ObservedV2装饰器和@Trace装饰器:解决@Observed装饰器和@ObjectLink调用过于复杂的问题.
- @Once:仅初始化同步一次。(@Once必须搭配@Param使用)
- @Event装饰器 :规范组件输出,修饰函数
- @Provider和@Consumer 跨组件层级双向同步
- @Monitor装饰器: 状态变量修改监听.
- @Computed装饰器:计算属性.(防止重复计算,为方法装饰器,仅能装饰getter方法)
- @Type :使得类属性序列化时不丢失类型信息,便于类的反序列化。