学习鸿蒙开发就不得不学习ArkTs语言,ArkTs是HarmonyOS应用的默认开发语言,在TypeScript(简称TS)生态基础上做了扩展,保持TS的基本风格,接下来就和小鱼一起学习ArkTS语言吧。
一、ArkTS语言概述
1、ArkTS与TypeScript的关系

TypeScript提供了一种更结构化的JavaScript编码方法,ArkTS保持了TypeScript的大部分语法,现有的TypeScript开发者提供高度兼容的体验,帮助移动开发者快速上手。
2、ArkTS的核心特性:静态类型、装饰器、响应式
1)静态类型是ArkTS最重要的特性之一
对比静态类型 vs 动态类型,举个例子🌰 :快餐店点餐
动态类型店(像 JavaScript)
特点 :你说"我要一个汉堡",店员就给你随便做一个
优点 :点餐快,很灵活
风险:可能给你一个素汉堡,而你本来想吃牛肉汉堡
javascript
// 就像这样
let 食物 = "汉堡"; // 现在它是字符串
食物 = 123; // 突然变成了数字!
食物 = {肉: "牛肉"}; // 又变成了对象!
// 运行时才知道会发生什么
静态类型店(像 ArkTS)
特点:菜单上明确分类:
- 🍔 牛肉汉堡:25元
- 🥗 素汉堡:20元
- 🍟 薯条:10元
流程:你点"牛肉汉堡",店员立即知道:
- 需要牛肉饼、面包、蔬菜
- 价格是25元
- 烹饪时间3分钟
javascript
// ArkTS写法
let 食物: string = "牛肉汉堡"; // 一开始就确定类型
// 食物 = 123; // 错误!编译器会说:"这里要的是食物,不是数字!"
总结:
静态类型 = 有详细图纸的建筑(提前规划,施工快,问题少)
动态类型 = 边想边建的房子(灵活,但容易出错,效率低)
2)装饰器
装饰器 = 不修改原代码,给类/方法/属性"添加功能"的特殊标记
举个例子🌰 : 🍰 蛋糕(原本的代码)
-
🎂 加奶油(装饰器1:@奶油装饰)
-
🍫 加巧克力(装饰器2:@巧克力装饰)
-
🍓 加草莓(装饰器3:@草莓装饰)
最后变成一个豪华蛋糕!
ArkTs 有很多装饰器,@Component:组件装饰器、@State:状态装饰器、@Entry:入口装饰器,还可以自定义装饰器,以后的博文中再学习吧,先举个例子:
javascript
@Entry
@Component
struct TabsExample {
@State colorArray: [string, string][] =
[['green', '#00CB87'], ['blue', '#007DFF'], ['yellow', '#FFBF00'], ['pink', '#E67C92']];
...
}
总结:装饰器就是 "不拆房子,只搞装修" 🏠 → 🏡
3)响应式:让UI"自动刷新"的魔法
举个例子🌰 :智能鱼缸 vs 普通鱼缸
🐠 普通鱼缸(非响应式)
你养了一缸鱼:
- 水温25°C → 鱼很快乐 🐟
- 水温降到20°C → 鱼不舒服,但你看不到变化
你必须:
- 用手摸水
- 看温度计
- 手动更新鱼缸的显示牌
🐟 智能鱼缸(响应式)
- 水温25°C → 鱼很快乐 🐟
- 水温降到20°C → 鱼缸自动:
🔴 灯光变红色
📢 发出警报声
📱 发送通知到手机
所有变化自动发生!
总结:
一句话理解响应式:"牵一发而动全身,但不用你亲自去动" 🧵 → 👕
3、开发环境中的ArkTS支持
鸿蒙为ArkTS提供了一站式、智能化、高效能的开发环境,从编码到上架全链路支持
1)开发工具支持:DevEco Studio
✅ 智能代码提示(ArkTS专属)
✅ 实时预览(所见即所得)
✅ 一键调试(真机/模拟器)
✅ 性能分析(ArkTS内存/CPU监控)
✅ 热重载(修改代码即时生效)
✅ 组件可视化拖拽
2)语言支持
| 支持类型 | 具体内容 | 示例 |
|---|---|---|
| 语法高亮 | ArkTS特有语法着色 | @State、@Component 特殊颜色 |
| 智能补全 | 组件/API自动补全 | 输入Text( 自动提示属性 |
| 类型检查 | 静态类型实时验证 | let a: string = 123 ❌ 立即报错 |
| 重构支持 | 重命名/提取组件等 | 右键 → Refactor → Extract Component |
| 代码格式化 | 统一代码风格 | Alt + Shift + F 自动格式化 |
3)调试与测试
javascript
// 多层次调试支持
1、️ UI调试:
- 组件树查看器
- 布局边界显示
- 性能Overlay(FPS/内存)
️2、 代码调试:
- 断点调试(ArkTS源码级)
- 变量监视
- 调用堆栈
️3、 测试框架:
- 单元测试(ArkTS单元测试框架)
- UI测试(自动化UI测试)
- 性能测试(启动时间/流畅度)
4)、工程管理与构建
javascript
// 项目结构支持
myApp/
├── entry/ # 主模块
│ ├── src/
│ │ ├── main/
│ │ │ ├── ets/ # ArkTS代码目录
│ │ │ │ ├── pages/ # 页面组件
│ │ │ │ ├── model/ # 数据模型
│ │ │ │ └── utils/ # 工具函数
│ │ │ └── resources/ # 资源文件
│ │ └── ohosTest/ # 测试代码
│ └── build-profile.json5 # 构建配置
├── build/ # 构建输出
└── oh-package.json5 # 依赖管理
二、基础类型
javascript
// 基本类型
let name: string = "鸿蒙"
let age: number = 3
let isActive: boolean = true
// 数组类型
let numbers: number[] = [1, 2, 3]
let strings: Array<string> = ["a", "b", "c"]
// 元组类型
let tuple: [string, number] = ["鸿蒙", 2021]
// 枚举类型
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
三、变量声明与作用域
1、let与const的区别
🌰 比喻:租房 vs 买房
不管是北漂、深漂还是沪漂,有多少程序员拥有了const 房,同时拥有几十年的房贷,不敢失业不敢辞职,想想就扎心...言归正传,继续学习😭
🏠 let = 租房(可以搬家)
javascript
let 我的地址 = "朝阳区101号";
console.log(我的地址); // "朝阳区101号"
// 可以随时搬家(重新赋值)
我的地址 = "海淀区202号"; // ✅ 没问题
我的地址 = "东城区303号"; // ✅ 继续搬家
🏡 const = 买房(地址固定)
javascript
const 我的房子地址 = "朝阳区101号";
console.log(我的房子地址); // "朝阳区101号"
// 不能换地址(不能重新赋值)
我的房子地址 = "海淀区202号"; // ❌ 报错:Assignment to constant variable
📊 核心区别对比表
| 特性 | let | const |
|---|---|---|
| 能否重新赋值 | ✅ | ❌ |
| 是否必须初始化 | 可以后赋值 | 必须 |
| 推荐使用场景 | 会变化的变量 | 不变的量 |
2、类型推断与类型注解
类型推断 vs 类型注解:让TS猜还是你告诉它?
🤖 类型推断:TS自动猜出类型,像智能助手
javascript
// 你:我有个变量
let 价格 = 100; // 没告诉类型
// TS助手:看到"100",自动推断:
// "哦,这是个数字!"
// 类型推断结果:let 价格: number
// 后续使用:
价格 = 200; // ✅ OK
价格 = "免费"; // ❌ 错误!类型推断为number了
📝 类型注解:你明确告诉TS类型,像下详细指令
javascript
// 你明确说:这是个字符串!
let 用户名: string = "夏小鱼";
// TS:收到!按字符串处理
// 后续使用:
用户名 = "本小鱼"; // ✅ OK
用户名 = 123; // ❌ 错误!你说了是string的
📊 核心区别对比表
| 特性 | 类型推断 | 类型注解 |
|---|---|---|
| 谁决定类型 | TypeScript编译器 | 开发者 |
| 代码量 | 少(不写类型) | 多(写类型) |
| 明确性 | 隐式 | 显式 |
| 使用场景 | 简单明显的情况 | 复杂或需要明确的情况 |
3、块级作用域与变量提升
🎪 块级作用域 vs 变量提升:变量的"活动范围"和"提前报名"
🌰 比喻:剧场里的座位:
🎭 块级作用域:分区管理
javascript
// 整个剧场(全局作用域)
{
// VIP区(块级作用域1)
let vip = "夏小鱼";
console.log(vip); // ✅ 能访问
}
{
// 普通区(块级作用域2)
let normal = "赵小鱼";
console.log(normal); // ✅ 能访问
}
// 剧场走廊(全局)
console.log(vip); // ❌ 不能访问VIP区的客人
console.log(normal); // ❌ 不能访问普通区的客人
🎪 变量提升:提前占座
javascript
console.log(vip); // 报错 Block-scoped variable 'vip' used before its declaration. <ArkTSCheck>
let vip = "夏小鱼";
javascript
// 1. 先把所有声明"提升"到最前面(占座)
let vip:string; // 提前声明(占座),值还没给
// 2. 然后执行代码
console.log(vip); // 报错Variable 'vip' is used before being assigned. <ArkTSCheck>
vip = "夏小鱼"; // 现在才赋值
四、函数定义与使用
函数声明引入一个函数,包含其名称、参数列表、返回类型和函数体。
以下示例是一个简单的函数和它的语法语义说明:
- 参数类型标注:a: number, b: number 显式声明参数类型为字符串类型。
- 返回值类型:: number 指定函数返回值为字符串类型。
javascript
// 函数声明
function add(a: number, b: number): number {
let c: number = a + b ;
return c;
}
可选参数函数:
javascript
function hello(name?: string) {
if (name == undefined) {
console.info('Hello!');
} else {
console.info(`Hello, ${name}!`);
}
}
可选参数的另一种形式,设置参数默认值
javascript
function multiply(n: number, coeff: number = 2): number {
return n * coeff;
}
multiply(2); // 返回2*2
multiply(2, 3); // 返回2*3
rest参数
rest参数允许函数接收一个不定长数组,用于处理不定数量的参数输入。
javascript
function sum(...numbers: number[]): number {
let res = 0;
for (let n of numbers) {
res += n;
}
return res;
}
sum(); // 返回0
sum(1, 2, 3); // 返回6
箭头函数
javascript
let sum = (x: number, y: number): number => {
return x + y;
}
函数重载
javascript
function foo(x: number): void; /* 第一个函数定义 */
function foo(x: string): void; /* 第二个函数定义 */
function foo(x: number | string): void { /* 函数实现 */
}
foo(123); // OK,使用第一个定义
foo('aa'); // OK,使用第二个定义
五、类与面向对象编程
类 = 设计蓝图
javascript
// 基础类定义
export class User {
// 属性
id: string; // 用户ID
login: string; // 登录用户名
name?: string; // 显示名称
avatar_url?: string; // 头像地址
created_at?: string; // 注册时间
html_url?: string; // GitHub主页地址
// 构造方法
constructor(id: string, login: string) {
this.id = id;
this.login = login;
}
}
什么是面向对象编程OOP
面向对象 = 用现实世界的方式组织代码
- 一切皆对象(Object)
- 对象有属性(数据)和方法(行为)
- 对象基于类(蓝图)创建
面向对象的四大支柱
1、封装
javascript
export class User {
// 属性
id: string; // 用户ID
login: string; // 登录用户名
name?: string; // 显示名称
avatar_url?: string; // 头像地址
created_at?: string; // 注册时间
html_url?: string; // GitHub主页地址
constructor(id: string, login: string) {
this.id = id;
this.login = login;
}
// ------------ 方法
// 获取显示名称
get displayName(): string {
return this.name || this.login || '匿名用户';
}
}
2、继承
javascript
export class LoginUser extends User {
// 属性
followers_url?: string; // 粉丝列表API地址
type?: string; // 用户类型(User/Organization)
url?: string; // API地址
bio?: string; // 个人简介
blog?: string; // 个人博客
company?: string; // 公司
email?: string; // 邮箱
followers?: number; // 粉丝数
following?: number; // 关注数
top_languages?: string[]; // 最常用编程语言
// 获取格式化粉丝数
get formattedFollowers(): string {
if (!this.followers) {
return '0';
}
if (this.followers >= 1000) {
return `${(this.followers / 1000).toFixed(1)}k`;
}
return this.followers.toString();
}
}
3、多态:同样的接口,不同的实现
javascript
interface Pay {
pay(amount: number): boolean;
}
class AliPay implements Pay {
pay(amount: number): boolean {
console.log(`支付宝支付:${amount}元`);
return true;
}
}
class WechatPay implements Pay {
pay(amount: number): boolean {
console.log(`微信支付:${amount}元`);
return true;
}
}
class UnionPay implements Pay {
pay(amount: number): boolean {
console.log(`银联支付:${amount}元`);
return true;
}
}
// 使用时不用关心具体是哪种支付
function pay(amount: number, pay: Pay) {
if (pay.pay(amount)) { // 多态调用
console.log("支付成功!");
}
}
4、抽象:定义规范,具体实现交给子类
javascript
// 抽象类:不能直接创建对象,只能被继承
abstract class 图形 {
// 抽象方法:只有声明,没有实现
abstract 计算面积(): number;
abstract 计算周长(): number;
// 可以有具体方法
显示信息(): void {
console.log(`面积: ${this.计算面积()}, 周长: ${this.计算周长()}`);
}
}
// 具体类:必须实现所有抽象方法
class 圆形 extends 图形 {
constructor(private 半径: number) {
super();
}
计算面积(): number {
return Math.PI * this.半径 * this.半径;
}
计算周长(): number {
return 2 * Math.PI * this.半径;
}
}
class 矩形 extends 图形 {
constructor(private 宽: number, private 高: number) {
super();
}
计算面积(): number {
return this.宽 * this.高;
}
计算周长(): number {
return 2 * (this.宽 + this.高);
}
}
// 使用
const 我的圆形 = new 圆形(5);
const 我的矩形 = new 矩形(4, 6);
我的圆形.显示信息(); // "面积: 78.54..., 周长: 31.41..."
我的矩形.显示信息(); // "面积: 24, 周长: 20"
// const 抽象图形 = new 图形(); // ❌ 错误!抽象类不能实例化
六、接口与泛型
接口已经在面向对象的多态中写了代码啦:interface Pay,
1、🔌 接口 = 插座标准
javascript
// 接口定义了一个"标准",不管什么设备都要符合这个标准才能插电
interface 电源插座 {
电压: number; // 必须是220V
插孔类型: string; // 必须是三孔
有地线: boolean; // 必须有地线
}
// 任何设备要实现这个接口,都必须满足这些要求
class 电视机 implements 电源插座 {
电压: number = 220;
插孔类型: string = "三孔";
有地线: boolean = true;
品牌: string = "索尼";
开机() {
console.log("电视机开机");
}
}
class 空调 implements 电源插座 {
电压: number = 220;
插孔类型: string = "三孔";
有地线: boolean = true;
功率: number = 2000;
制冷() {
console.log("空调开始制冷");
}
}
// 电源接口检查
function 检查电器安全(电器: 电源插座): boolean {
return 电器.电压 === 220 && 电器.有地线;
}
// 任何实现了电源接口的电器都可以使用这个函数
const 我的电视 = new 电视机();
const 我的空调 = new 空调();
console.log(检查电器安全(我的电视)); // ✅ true
console.log(检查电器安全(我的空调)); // ✅ true
2、🧱 泛型 = 万能模具
javascript
// 泛型就像一个"万能模具",可以制造各种形状的东西
class 盒子<T> { // T是类型参数,像模具的形状参数
内容: T;
constructor(内容: T) {
this.内容 = 内容;
}
获取内容(): T {
return this.内容;
}
更换内容(新内容: T): void {
this.内容 = 新内容;
}
}
// 用同一个模具制造不同形状的东西
const 数字盒子 = new 盒子<number>(100); // T = number
const 字符串盒子 = new 盒子<string>("hello"); // T = string
const 对象盒子 = new 盒子<{name: string}>({ name: "小明" });
console.log(数字盒子.获取内容()); // 100 (类型是number)
console.log(字符串盒子.获取内容()); // "hello" (类型是string)
// 类型安全!
数字盒子.更换内容(200); // ✅ 正确
// 数字盒子.更换内容("文本"); // ❌ 错误!必须是number
📊 核心区别对比表
| 特性 | 接口 | 范型 |
|---|---|---|
| 作用 | 定义标准 | 创建可复用的类型 |
| 关注点 | 结构/形状 | 类型参数化 |
| 使用场景 | 多态、代码约束 | 容器、工具函数、复用逻辑 |
七、实践任务
1、基础任务
根据搜索用户接口文档:https://docs.atomgit.com/docs/apis/get-api-v-5-search-users
创建AtomGit 的用户类,包含id,login,name,avatar_url,created_at,html_url属性;其中name,avatar_url,created_at,html_url为可选参数
实现用户名显示方法disPlayName,login和name都为空显示"匿名用户"
有没有发现答案已经在前面的博文里面啦,找不到的留言小鱼帮你一起进步!
2、进阶任务
根据获取一个用户接口文档:https://docs.atomgit.com/docs/apis/get-api-v-5-users-username
创建一个用户类,并格式化粉丝数
javascript
export class LoginUser extends User {
// 属性
followers_url?: string; // 粉丝列表API地址
type?: string; // 用户类型(User/Organization)
url?: string; // API地址
bio?: string; // 个人简介
blog?: string; // 个人博客
company?: string; // 公司
email?: string; // 邮箱
followers?: number; // 粉丝数
following?: number; // 关注数
top_languages?: string[]; // 最常用编程语言
// 获取格式化粉丝数
get formattedFollowers(): string {
if (!this.followers) {
return '0';
}
if (this.followers >= 1000) {
return `${(this.followers / 1000).toFixed(1)}k`;
}
return this.followers.toString();
}
}
又是完美的一天 🎉