4、ArkTS语言基础(下):模块化与导入导出、异步编程(Promise与async/await)、装饰器(@Component等)入门、常用内置API
好,咱们接着聊。上一节我们把 ArkTS 的类型系统、变量声明和函数讲透了。这一节,我带你攻克几个真正决定你能否写出“鸿蒙味儿”代码的关键点:模块化、异步编程、装饰器,还有那些高频内置 API。
说实话,这些内容在刚接触时可能会觉得有点绕。但别担心,我当年从 Java 转到 TypeScript 时,也被这些概念折磨过。咱们一个一个来,保证你听完就能上手。
4.1 模块化与导入导出:把代码拆成“积木”
为什么要模块化?说白了,就是别把所有代码塞进一个文件里。你想想看,一个项目几千行代码,全写在一个文件里,找 bug 就像大海捞针。
ArkTS 沿用了 ES6 的模块化标准。核心就两个关键字:export 和 import。
4.1.1 导出(export)
你可以把模块理解成一个“工具箱”。export 就是把工具从箱子里拿出来,让别人能用。
命名导出:
// utils.ets
export function formatDate(date: Date): string {
return date.toISOString().split('T')[0];
}
export const API_BASE_URL = 'https://api.example.com';
export class User {
name: string;
age: number;
}
默认导出:
// Logger.ets
export default class Logger {
static log(msg: string) {
console.info('[LOG]: ' + msg);
}
}
4.1.2 导入(import)
有导出就有导入。就像你从工具箱里拿工具出来用。
// main.ets
import { formatDate, API_BASE_URL } from './utils';
import Logger from './Logger';
let today = formatDate(new Date());
Logger.log('今天日期:' + today);
重命名导入:
import { formatDate as fd } from './utils';
./,排查了半小时。在鸿蒙项目中,相对路径必须以 ./ 或 ../ 开头。
4.2 异步编程:Promise 与 async/await
鸿蒙开发中,网络请求、文件读写、数据库操作,这些都是异步的。说白了,就是你不能让 App 卡在那里等结果。
ArkTS 的异步方案和现代 JavaScript 完全一致:Promise 和 async/await。
4.2.1 Promise 基础
Promise 就像一个“承诺”。它有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。
function fetchUserData(userId: string): Promise<User> {
return new Promise((resolve, reject) => {
// 模拟网络请求
setTimeout(() => {
if (userId) {
resolve({ name: '张三', age: 25 });
} else {
reject(new Error('用户ID不能为空'));
}
}, 1000);
});
}
// 使用 Promise
fetchUserData('123')
.then(user => {
console.info('用户数据:' + JSON.stringify(user));
})
.catch(error => {
console.error('请求失败:' + error.message);
});
避坑指南:我曾经在项目中忘了写 .catch(),结果 Promise 抛出的错误直接导致应用闪退。记住:每个 Promise 都必须有错误处理。
4.2.2 async/await:更优雅的写法
说实话,.then() 链式调用写多了,代码会变得很难看。尤其是多个异步操作有依赖关系时,回调地狱就来了。
async/await 就是来解决这个问题的。它让异步代码看起来像同步代码一样直观。
async function loadUserProfile(userId: string): Promise<void> {
try {
let user = await fetchUserData(userId);
console.info('用户信息加载完成');
// 可以继续 await 其他异步操作
let orders = await fetchUserOrders(user.id);
console.info('订单数量:' + orders.length);
} catch (error) {
console.error('加载失败:' + error.message);
}
}
嗯,这里要注意:await 只能在 async 函数内部使用。这个规则我刚开始也经常忘。
4.3 装饰器入门:@Component 等
装饰器是 ArkTS 的一大特色。说白了,它就是一种特殊的声明,可以附加在类、方法、属性上,用来修改它们的行为。
在鸿蒙开发中,你用得最多的就是 @Component、@State、@Prop 这些。
4.3.1 @Component:声明一个自定义组件
@Component
struct MyButton {
build() {
Button('点击我')
.onClick(() => {
console.info('按钮被点击了');
});
}
}
看到 @Component 了吗?它告诉编译器:这是一个 UI 组件。你想想看,如果没有这个装饰器,编译器怎么知道一个结构体是普通数据还是 UI 组件?
4.3.2 @State:让数据驱动 UI
@Component
struct Counter {
@State count: number = 0;
build() {
Column() {
Text('计数:' + this.count)
.fontSize(20);
Button('增加')
.onClick(() => {
this.count++;
});
}
}
}
4.3.3 @Prop:父子组件传值
@Component
struct ChildComponent {
@Prop message: string;
build() {
Text(this.message);
}
}
@Component
struct ParentComponent {
build() {
ChildComponent({ message: '来自父组件的数据' });
}
}
4.4 常用内置 API
ArkTS 提供了一些非常实用的内置 API。我挑几个高频的给你讲讲。
4.4.1 控制台输出
console.info('这是一条信息');
console.warn('这是一条警告');
console.error('这是一条错误');
调试时,console 是你的好帮手。我个人习惯在关键逻辑处加 console.info,方便追踪执行流程。
4.4.2 定时器
// 延迟执行
setTimeout(() => {
console.info('1秒后执行');
}, 1000);
// 定时执行
let intervalId = setInterval(() => {
console.info('每秒执行一次');
}, 1000);
// 清除定时器
clearInterval(intervalId);
4.4.3 JSON 处理
let user = { name: '李四', age: 30 };
let jsonStr = JSON.stringify(user);
console.info(jsonStr); // {"name":"李四","age":30}
let parsedUser = JSON.parse(jsonStr);
console.info(parsedUser.name); // 李四
4.4.4 数学计算
let max = Math.max(10, 20, 30); // 30
let min = Math.min(10, 20, 30); // 10
let random = Math.random(); // 0到1之间的随机数
let rounded = Math.round(3.7); // 4
4.5 综合示例:一个完整的异步数据加载组件
最后,我把今天讲的内容串起来,给你看一个完整的例子。
// UserService.ets
export class UserService {
static async fetchUser(id: string): Promise<User> {
// 模拟网络请求
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: id, name: '王五', age: 28 });
}, 500);
});
}
}
// UserProfile.ets
import { UserService } from './UserService';
@Component
struct UserProfile {
@State userName: string = '加载中...';
@State userAge: number = 0;
async aboutToAppear() {
try {
let user = await UserService.fetchUser('001');
this.userName = user.name;
this.userAge = user.age;
} catch (error) {
console.error('加载用户数据失败:' + error.message);
}
}
build() {
Column() {
Text('用户名:' + this.userName)
.fontSize(18);
Text('年龄:' + this.userAge)
.fontSize(18);
}
.padding(20);
}
}
看到没?模块化导出、异步加载、装饰器驱动 UI,全用上了。这就是鸿蒙端云一体化开发的基础套路。
好了,这一节的内容就到这里。下一节我们开始真正搭建项目结构,到时候这些知识你都会用得上。