本文字数:2560字 | 预计阅读时间:10分钟
适用人群:有JavaScript/TypeScript基础、Java/Kotlin开发者、零基础但想系统学习鸿蒙开发
前置知识:建议先阅读本系列第1篇《环境搭建与第一个应用》
系列导航:本文是《鸿蒙开发系列》第2篇,下篇将深入讲解ArkUI组件布局
一、ArkTS初探:鸿蒙的专属开发语言
1.1 什么是ArkTS?
ArkTS是鸿蒙生态的应用开发语言,它基于TypeScript(简称TS)扩展,并针对鸿蒙系统的特性进行了深度优化。如果你熟悉TypeScript,那么学习ArkTS将事半功倍。
1.2 为什么选择ArkTS而不是其他语言?
| 语言 | 优点 | 在鸿蒙中的定位 |
|---|---|---|
| ArkTS | 类型安全、性能优化、鸿蒙原生支持 | 主推语言,全场景应用开发 |
| JavaScript | 灵活、生态丰富 | 兼容运行,但性能不如ArkTS |
| Java | 成熟、稳定 | 主要用于系统服务和底层开发 |
| C/C++ | 高性能、底层控制 | 驱动开发、高性能计算 |
1.3 ArkTS与TypeScript的核心差异
typescript
复制下载
// TypeScript中的类
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// ArkTS中的增强(增加了装饰器支持)
@Component
struct PersonComponent {
@State name: string = '';
@State age: number = 0;
// 更多鸿蒙特有的装饰器和API
}
二、基础类型系统:让代码更安全
2.1 基本数据类型
ArkTS继承了TypeScript的类型系统,并做了一些扩展:
typescript
复制下载
// 1. 数值类型 - 支持整数和浮点数
let decimal: number = 6;
let hex: number = 0xf00d; // 十六进制
let binary: number = 0b1010; // 二进制
let octal: number = 0o744; // 八进制
let float: number = 3.14;
// 2. 字符串类型 - 三种定义方式
let name1: string = "张三";
let name2: string = '李四';
let template: string = `我的名字是${name1},年龄${decimal}岁`;
// 3. 布尔类型
let isDone: boolean = false;
let isHarmony: boolean = true;
// 4. 数组类型 - 两种声明方式
let list1: number[] = [1, 2, 3];
let list2: Array<string> = ['a', 'b', 'c'];
// 5. 元组类型 - 固定长度的数组
let tuple: [string, number, boolean];
tuple = ['鸿蒙', 4.0, true]; // 正确
// tuple = [4.0, '鸿蒙', true]; // 错误:类型不匹配
2.2 特殊类型
typescript
复制下载
// 1. Any类型 - 任意类型(慎用,会失去类型检查)
let notSure: any = 4;
notSure = "可能是字符串";
notSure = false; // 也可以赋值为布尔值
// 2. Unknown类型 - 更安全的Any
let value: unknown;
value = 'Hello';
value = 42;
// let str: string = value; // 错误:需要类型断言
let str: string = value as string; // 正确:使用类型断言
// 3. Void类型 - 没有返回值
function warnUser(): void {
console.log("这是一个警告");
}
// 4. Null和Undefined
let u: undefined = undefined;
let n: null = null;
// 5. Never类型 - 永远不会发生的类型
function error(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
三、变量声明与作用域
3.1 三种声明方式对比
typescript
复制下载
// 1. var - 函数作用域(不推荐在ArkTS中使用)
function varTest() {
var x = 10;
if (true) {
var x = 20; // 同一个变量!
console.log(x); // 20
}
console.log(x); // 20
}
// 2. let - 块级作用域(推荐)
function letTest() {
let x = 10;
if (true) {
let x = 20; // 不同的变量
console.log(x); // 20
}
console.log(x); // 10
}
// 3. const - 常量(不可重新赋值)
const PI = 3.14159;
// PI = 3.14; // 错误:常量不能重新赋值
const person = { name: '张三' };
person.name = '李四'; // 正确:对象的属性可以修改
// person = { name: '王五' }; // 错误:不能重新赋值
3.2 类型注解与类型推断
typescript
复制下载
// 显式类型注解
let userName: string = "鸿蒙开发者";
let userAge: number = 25;
let isDeveloper: boolean = true;
// 类型推断 - TypeScript/ArkTS会自动推断类型
let company = "华为"; // 推断为string
let version = 4.0; // 推断为number
let released = true; // 推断为boolean
// 联合类型
let id: string | number;
id = "ABC123"; // 正确
id = 123456; // 正确
// id = true; // 错误:只能是string或number
// 类型别名
type UserID = string | number;
type Callback = (data: string) => void;
let userId: UserID = "user_001";
let onSuccess: Callback = (result) => {
console.log(`结果:${result}`);
};
四、函数:ArkTS的核心构建块
4.1 函数定义与调用
typescript
复制下载
// 1. 命名函数
function add(x: number, y: number): number {
return x + y;
}
// 2. 函数表达式
const multiply = function(x: number, y: number): number {
return x * y;
};
// 3. 箭头函数(推荐)
const divide = (x: number, y: number): number => {
return x / y;
};
// 4. 简写箭头函数
const square = (x: number): number => x * x;
// 调用函数
console.log(add(5, 3)); // 8
console.log(multiply(4, 6)); // 24
console.log(divide(10, 2)); // 5
console.log(square(9)); // 81
4.2 函数参数高级特性
typescript
复制下载
// 1. 可选参数
function buildName(firstName: string, lastName?: string) {
return lastName ? `${firstName} ${lastName}` : firstName;
}
console.log(buildName("张")); // 张
console.log(buildName("张", "三")); // 张三
// 2. 默认参数
function createDevice(name: string, type: string = "手机") {
return `${name} - ${type}`;
}
console.log(createDevice("Mate60")); // Mate60 - 手机
console.log(createDevice("Watch4", "手表")); // Watch4 - 手表
// 3. 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
// 4. 函数重载
function format(input: string): string;
function format(input: number): string;
function format(input: string | number): string {
if (typeof input === 'string') {
return `字符串: ${input}`;
} else {
return `数字: ${input}`;
}
}
console.log(format("鸿蒙")); // 字符串: 鸿蒙
console.log.format(4.0); // 数字: 4.0
五、类与面向对象编程
5.1 类的定义与使用
typescript
复制下载
// 基础类定义
class Device {
// 属性
name: string;
type: string;
private serialNumber: string; // 私有属性
// 构造函数
constructor(name: string, type: string, serial: string) {
this.name = name;
this.type = type;
this.serialNumber = serial;
}
// 方法
getInfo(): string {
return `${this.name} (${this.type})`;
}
// 私有方法
private getSerial(): string {
return this.serialNumber;
}
// 静态方法
static createDefault(): Device {
return new Device("默认设备", "未知", "000000");
}
}
// 创建实例
const phone = new Device("华为手机", "智能手机", "SN123456");
console.log(phone.getInfo()); // 华为手机 (智能手机)
// console.log(phone.serialNumber); // 错误:私有属性不能访问
// 调用静态方法
const defaultDevice = Device.createDefault();
5.2 继承与多态
typescript
复制下载
// 基类
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): string {
return "动物叫声";
}
}
// 派生类
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name); // 调用父类构造函数
this.breed = breed;
}
// 重写父类方法
makeSound(): string {
return "汪汪汪";
}
// 新增方法
fetch(): string {
return `${this.name} 去捡球了`;
}
}
// 使用
const myDog = new Dog("旺财", "金毛");
console.log(myDog.makeSound()); // 汪汪汪
console.log(myDog.fetch()); // 旺财 去捡球了
5.3 抽象类与接口
typescript
复制下载
// 接口定义
interface USBDevice {
readonly version: string; // 只读属性
connect(): boolean;
disconnect(): void;
}
// 抽象类
abstract class StorageDevice {
abstract capacity: number;
abstract readData(): string;
abstract writeData(data: string): void;
// 可以有具体实现的方法
getInfo(): string {
return `存储设备,容量: ${this.capacity}GB`;
}
}
// 实现接口和继承抽象类
class USBFlashDrive extends StorageDevice implements USBDevice {
capacity: number;
readonly version: string = "3.0";
constructor(capacity: number) {
super();
this.capacity = capacity;
}
connect(): boolean {
console.log("USB设备已连接");
return true;
}
disconnect(): void {
console.log("USB设备已断开");
}
readData(): string {
return "从USB读取数据";
}
writeData(data: string): void {
console.log(`写入数据: ${data}`);
}
}
// 使用
const flashDrive = new USBFlashDrive(64);
flashDrive.connect();
console.log(flashDrive.getInfo());
六、装饰器:ArkTS的魔法特性
6.1 内置装饰器
typescript
复制下载
// 1. @Entry - 页面入口装饰器
@Entry
@Component
struct IndexPage {
// 2. @State - 状态装饰器
@State count: number = 0;
@State message: string = 'Hello';
// 3. @Prop - 父子组件传值
@Prop title: string = '默认标题';
// 4. @Link - 双向数据绑定
@Link isActive: boolean;
// 5. @Watch - 监听状态变化
@Watch('onCountChange')
@State watchedCount: number = 0;
onCountChange(): void {
console.log(`计数变化: ${this.watchedCount}`);
}
// 构建函数
build() {
// UI构建代码
}
}
// 6. 自定义装饰器
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`调用方法: ${propertyKey}`);
console.log(`参数: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`返回值: ${result}`);
return result;
};
return descriptor;
}
class Calculator {
@log
add(x: number, y: number): number {
return x + y;
}
}
七、模块化与代码组织
7.1 导出与导入
typescript
复制下载
// user.ts - 导出模块
export interface User {
id: number;
name: string;
age: number;
}
export class UserService {
static getUser(id: number): User {
return { id, name: "测试用户", age: 25 };
}
}
// 默认导出
export default class Logger {
static log(message: string): void {
console.log(`[LOG] ${message}`);
}
}
// main.ts - 导入模块
import Logger from './user'; // 默认导入
import { User, UserService } from './user'; // 命名导入
// 使用
const user: User = UserService.getUser(1);
Logger.log(`用户: ${user.name}`);
7.2 命名空间
typescript
复制下载
// 定义命名空间
namespace HarmonyUtils {
export function formatDate(date: Date): string {
return date.toLocaleDateString();
}
export namespace Validators {
export function isEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email);
}
}
}
// 使用
console.log(HarmonyUtils.formatDate(new Date()));
console.log(HarmonyUtils.Validators.isEmail("test@huawei.com"));
八、实战示例:用户管理系统
typescript
复制下载
// 定义用户类型
type Gender = 'male' | 'female' | 'other';
interface IUser {
id: string;
name: string;
age: number;
gender: Gender;
email: string;
}
// 用户类
class User implements IUser {
constructor(
public id: string,
public name: string,
public age: number,
public gender: Gender,
public email: string
) {}
// 获取用户信息
getInfo(): string {
return `${this.name} (${this.age}岁, ${this.gender})`;
}
// 验证邮箱
isValidEmail(): boolean {
return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(this.email);
}
}
// 用户管理类
class UserManager {
private users: Map<string, User> = new Map();
// 添加用户
addUser(user: User): boolean {
if (this.users.has(user.id)) {
return false;
}
if (!user.isValidEmail()) {
console.error('邮箱格式不正确');
return false;
}
this.users.set(user.id, user);
return true;
}
// 获取用户
getUser(id: string): User | undefined {
return this.users.get(id);
}
// 获取所有用户
getAllUsers(): User[] {
return Array.from(this.users.values());
}
// 筛选用户
filterUsers(predicate: (user: User) => boolean): User[] {
return this.getAllUsers().filter(predicate);
}
}
// 使用示例
const userManager = new UserManager();
// 创建用户
const user1 = new User('001', '张三', 25, 'male', 'zhangsan@huawei.com');
const user2 = new User('002', '李四', 30, 'female', 'lisi@harmonyos.com');
// 添加用户
userManager.addUser(user1);
userManager.addUser(user2);
// 查询用户
console.log(userManager.getUser('001')?.getInfo()); // 张三 (25岁, male)
// 筛选成年用户
const adults = userManager.filterUsers(user => user.age >= 18);
console.log(`成年用户数量: ${adults.length}`);
九、最佳实践与常见错误
9.1 最佳实践
typescript
复制下载
// 1. 始终使用严格模式
// 在tsconfig.json中配置
{
"compilerOptions": {
"strict": true
}
}
// 2. 优先使用const,其次是let,避免var
const APP_NAME = '鸿蒙应用';
let isLoading = false;
// 3. 明确函数返回值类型
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
// 4. 使用接口定义复杂对象结构
interface AppConfig {
name: string;
version: string;
apiUrl: string;
timeout?: number; // 可选属性
}
// 5. 合理使用类型断言
const element = document.getElementById('root') as HTMLDivElement;
9.2 常见错误及解决
typescript
复制下载
// 错误1:类型不匹配
let count: number = 10;
// count = "20"; // 错误:不能将字符串赋值给数值类型
// 错误2:访问不存在的属性
interface Product {
name: string;
price: number;
}
const product: Product = { name: "手机", price: 3999 };
// console.log(product.discount); // 错误:discount不存在
// 错误3:未处理可选参数
function greet(name?: string) {
// console.log(`Hello, ${name.toUpperCase()}`); // 错误:name可能为undefined
console.log(`Hello, ${name?.toUpperCase()}`); // 正确:使用可选链
}
// 错误4:错误的类型断言
const data: any = "这是一个字符串";
// const length: number = (data as number).length; // 运行时错误
const length: number = (data as string).length; // 正确
十、学习资源与下期预告
10.1 官方学习资源
- ArkTS官方文档
- TypeScript官网(先学TS再学ArkTS)
- 华为开发者学堂
10.2 实践建议
- 每天练习:至少写30分钟ArkTS代码
- 项目驱动:尝试用ArkTS实现一个小工具
- 阅读源码:学习鸿蒙官方示例项目
- 参与社区:在华为开发者论坛提问和解答
10.3 下期预告:《鸿蒙开发之:ArkUI组件布局全解析》
下篇文章将深入讲解:
- 常用UI组件:Text、Button、Image、Input等
- 六大布局方式:Flex、Column、Row、Stack、Grid、List
- 组件样式与主题配置
- 实战:构建一个完整的用户界面 可以加入班级学习鸿蒙了:developer.huawei.com/consumer/cn…