ArkTS 基础入门教程 —— 从零开始学鸿蒙应用开发

作者:zyz
时间:2026-05-18
适用版本:HarmonyOS NEXT / API 12+
阅读提示:本文假设读者已有基本的 TypeScript/JavaScript 基础,如果没有也无需担心,照着写也能很快上手。


目录

  1. 什么是 ArkTS
  2. 环境搭建
  3. 基本语法
  4. 声明式 UI 入门
  5. 常用组件
  6. 状态管理
  7. 页面路由
  8. 实战:Todo 应用
  9. 总结

一、什么是 ArkTS

ArkTS 是华为为 HarmonyOS 生态量身打造的编程语言,它是 TypeScript 的超集,在此基础上增加了声明式 UI 能力和状态管理机制。

为什么选择 ArkTS?

特性 说明
TS 超集 所有合法的 TS/JS 代码都可以在 ArkTS 中运行
声明式 UI 类似 SwiftUI / Flutter,用代码描述界面,框架自动渲染
状态驱动 数据变了,UI 自动刷新,告别手动操作 DOM
强类型安全 编译期就能捕获大量错误,减少线上事故
方舟编译器 直接编译为机器码,性能接近原生

一个最简示例

@Entry
@Component
struct HelloPage {
  @State message: string = 'Hello ArkTS';

  build() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

运行后,屏幕中央会显示加粗的 “Hello ArkTS”。这就是 ArkTS 的"味道"——用 build() 方法描述界面,用 @State 管理数据。


二、环境搭建

2.1 安装 DevEco Studio

  1. 访问 HarmonyOS 开发者官网
  2. 下载 DevEco Studio(推荐 5.0+ 版本)
  3. 按向导安装,一路 Next 即可
  4. 首次启动会提示安装 SDK,勾选 HarmonyOS NEXT 下的 API 12+

2.2 创建项目

File → New → Create Project → Empty Ability → Next
  • Project nameMyFirstApp
  • Bundle namecom.example.myfirstapp
  • Save location:自定义
  • Compile SDK:选最新的 API 12+
  • Model:选 Stage

点击 Finish,项目就创建好了。入口文件是 src/main/ets/pages/Index.ets

2.3 项目结构一览

MyFirstApp/
├── AppScope/          # 应用全局配置
│   └── app.json5      # 应用包名、版本号等
├── entry/
│   └── src/main/
│       ├── ets/       # ArkTS 源码
│       │   ├── entryability/
│       │   │   └── EntryAbility.ets
│       │   └── pages/
│       │       └── Index.ets    # 首页
│       └── resources/ # 资源文件
├── build-profile.json5
└── oh-package.json5   # 依赖管理

三、基本语法

ArkTS 继承了 TypeScript 的全部语法,下面只列出日常开发中最常用的部分。

3.1 变量声明

let name: string = '张三';          // 可变
const PI: number = 3.14;           // 不可变
let isDone: boolean = true;
let list: number[] = [1, 2, 3];
let tuple: [string, number] = ['age', 18];

3.2 函数

// 普通函数
function add(a: number, b: number): number {
  return a + b;
}

// 箭头函数(最常用)
const multiply = (a: number, b: number): number => a * b;

// 可选参数 & 默认值
function greet(name: string, greeting: string = '你好'): string {
  return `${greeting}${name}`;
}

3.3 接口与类

interface User {
  id: number;
  name: string;
  age?: number;  // 可选属性
}

class Student implements User {
  id: number;
  name: string;

  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  study(): void {
    console.log(`${this.name} 在学习`);
  }
}

3.4 枚举

enum Color {
  Red = '#FF0000',
  Green = '#00FF00',
  Blue = '#0000FF'
}

let primaryColor: Color = Color.Blue;

3.5 联合类型 & 类型守卫

type Result = string | number;

function processResult(value: Result): string {
  if (typeof value === 'string') {
    return value.toUpperCase();   // 这里 TS 知道 value 是 string
  }
  return value.toFixed(2);        // 这里 know value 是 number
}

四、声明式 UI 入门

这是 ArkTS 最核心的部分。先理解几个关键概念:

4.1 装饰器

装饰器 作用
@Entry 标记为页面入口(可被路由跳转)
@Component 标记为自定义组件
@State 组件内部状态,变化时触发 UI 刷新
@Prop 父传子的单向数据流
@Link 父传子的双向数据绑定
@Provide / @Consume 跨层级数据共享(无需逐层传递)
@StorageLink 与 AppStorage 双向绑定
@ObjectLink / @Observed 对象/数组的深层状态监听

4.2 build() 方法

每个 @Component 必须实现 build() 方法,返回 UI 描述:

@Component
struct MyCard {
  @State title: string = '默认标题';

  build() {
    Column() {
      Text(this.title)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
      Divider()
      Text('这是卡片内容区域')
        .fontSize(14)
        .fontColor('#666')
    }
    .width('90%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(12)
    .shadow({ radius: 8, color: '#10000000' })
  }
}

4.3 布局三剑客

// Column:垂直排列
Column({ space: 10 }) {
  Text('第一行')
  Text('第二行')
}

// Row:水平排列
Row({ space: 10 }) {
  Text('左')
  Text('右')
}

// Flex:弹性布局(更灵活)
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
  Text('项目1').layoutWeight(1)
  Text('项目2').layoutWeight(1)
  Text('项目3').layoutWeight(1)
}

4.4 属性链式调用

所有组件都支持链式调用来设置样式:

Text('Hello')
  .fontSize(16)                     // 字号
  .fontColor('#333')                // 颜色
  .fontWeight(FontWeight.Medium)    // 字重
  .textAlign(TextAlign.Center)      // 对齐
  .maxLines(2)                      // 最大行数
  .textOverflow({ overflow: TextOverflow.Ellipsis })  // 溢出省略
  .onClick(() => {                  // 点击事件
    console.log('被点击了');
  })

五、常用组件

5.1 Text(文本)

Text('这是一段文本')
  .fontSize(16)
  .fontColor(Color.Black)

5.2 Image(图片)

// 本地资源
Image($r('app.media.icon'))
  .width(60)
  .height(60)

// 网络图片
Image('https://example.com/avatar.png')
  .width(60)
  .height(60)
  .borderRadius(30)  // 圆形头像

5.3 Button(按钮)

Button('点击我')
  .type(ButtonType.Capsule)
  .fontSize(16)
  .backgroundColor('#007AFF')
  .borderRadius(8)
  .onClick(() => {
    // 处理点击
  })

5.4 TextInput(输入框)

TextInput({ placeholder: '请输入用户名' })
  .width('100%')
  .height(44)
  .borderRadius(8)
  .backgroundColor('#F5F5F5')
  .onChange((value: string) => {
    console.log('输入内容:', value);
  })

5.5 List(列表)

List() {
  ForEach(this.dataArray, (item: string, index: number) => {
    ListItem() {
      Text(item)
        .width('100%')
        .padding(12)
    }
  }, (item: string) => item)  // key 生成器,必须提供
}
.divider({ strokeWidth: 1, color: '#EEE' })

5.6 Scroll(滚动区域)

Scroll() {
  Column() {
    // 内容可以很长,自动滚动
    ForEach([...Array(50).keys()], (i: number) => {
      Text(`${i + 1}`).padding(8)
    })
  }
}
.width('100%')
.height('100%')

5.7 条件渲染 & 循环

// 条件渲染
if (this.isLoggedIn) {
  Text('欢迎回来')
} else {
  Button('去登录')
}

// 循环渲染
ForEach(this.items, (item: Item, index: number) => {
  ListItem() {
    Text(item.name)
  }
}, (item: Item) => item.id.toString())

六、状态管理

这是 ArkTS 最精髓的部分。核心原则:状态变了,界面自动跟着变

6.1 @State —— 组件内部状态

@Component
struct Counter {
  @State count: number = 0;

  build() {
    Column({ space: 20 }) {
      Text(`计数:${this.count}`).fontSize(30)

      Row({ space: 16 }) {
        Button('+1').onClick(() => {
          this.count++;  // 改了数据,UI 自动刷新
        })
        Button('-1').onClick(() => {
          this.count--;
        })
      }
    }
  }
}

6.2 @Prop —— 父传子(单向)

// 子组件
@Component
struct ChildItem {
  @Prop title: string;   // 从父组件接收,不能自己改父组件的值

  build() {
    Text(this.title).fontSize(16)
  }
}

// 父组件
@Component
struct ParentPage {
  @State parentTitle: string = '来自父组件';

  build() {
    ChildItem({ title: this.parentTitle })
  }
}

6.3 @Link —— 父传子(双向绑定)

@Component
struct ToggleSwitch {
  @Link isOn: boolean;  // 子组件改了,父组件也跟着变

  build() {
    Toggle({ type: ToggleType.Switch, isOn: this.isOn })
      .onChange((value: boolean) => {
        this.isOn = value;
      })
  }
}

6.4 @Provide / @Consume —— 跨层级共享

不用一层层传 props,子孙组件直接拿:

// 祖先组件
@Component
struct GrandParent {
  @Provide('theme') themeColor: string = '#007AFF';

  build() { /* ... */ }
}

// 任意后代组件(中间隔多少层都行)
@Component
struct DeepChild {
  @Consume('theme') themeColor: string;

  build() {
    Text('主题色').fontColor(this.themeColor)
  }
}

七、页面路由

HarmonyOS 使用 router 模块进行页面跳转。

7.1 跳转页面

import { router } from '@kit.ArkUI';

// 跳转到目标页
router.pushUrl({
  url: 'pages/DetailPage',  // 目标页路径(相对于 src/main/ets/)
  params: {
    id: 123,
    title: '详情标题'
  }
});

// 替换当前页(无法返回)
router.replaceUrl({
  url: 'pages/LoginPage'
});

7.2 接收参数

// DetailPage.ets
import { router } from '@kit.ArkUI';

@Entry
@Component
struct DetailPage {
  @State id: number = 0;
  @State title: string = '';

  aboutToAppear(): void {
    const params = router.getParams() as Record<string, Object>;
    this.id = params?.['id'] as number;
    this.title = params?.['title'] as string;
  }

  build() {
    Column() {
      Text(`ID: ${this.id}`)
      Text(this.title)
    }
  }
}

7.3 返回上一页

router.back();  // 返回上一页

八、实战:Todo 应用

把上面的知识串起来,写一个完整的 Todo 应用。

8.1 页面代码

// pages/TodoPage.ets
import { router } from '@kit.ArkUI';

class TodoItem {
  id: number;
  text: string;
  done: boolean;

  constructor(id: number, text: string, done: boolean = false) {
    this.id = id;
    this.text = text;
    this.done = done;
  }
}

@Entry
@Component
struct TodoPage {
  @State todos: TodoItem[] = [];
  @State inputText: string = '';
  private nextId: number = 0;

  addTodo(): void {
    if (this.inputText.trim() === '') {
      return;
    }
    this.todos = [
      ...this.todos,
      new TodoItem(this.nextId++, this.inputText.trim())
    ];
    this.inputText = '';
  }

  toggleTodo(id: number): void {
    this.todos = this.todos.map(item => {
      if (item.id === id) {
        return new TodoItem(item.id, item.text, !item.done);
      }
      return item;
    });
  }

  deleteTodo(id: number): void {
    this.todos = this.todos.filter(item => item.id !== id);
  }

  build() {
    Column() {
      // 标题栏
      Text('📋 我的待办')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .width('100%')
        .padding({ left: 16, top: 16, bottom: 8 })

      // 输入区域
      Row({ space: 8 }) {
        TextInput({ placeholder: '输入要做的事...' })
          .layoutWeight(1)
          .height(44)
          .borderRadius(8)
          .backgroundColor('#F5F5F5')
          .onChange((value: string) => {
            this.inputText = value;
          })

        Button('添加')
          .height(44)
          .padding({ left: 16, right: 16 })
          .borderRadius(8)
          .onClick(() => {
            this.addTodo();
          })
      }
      .width('100%')
      .padding(16)

      // 统计
      Text(`${this.todos.length} 项,已完成 ${this.todos.filter(t => t.done).length}`)
        .fontSize(13)
        .fontColor('#999')
        .width('100%')
        .padding({ left: 16, bottom: 8 })

      // 列表
      List() {
        ForEach(this.todos,
          (item: TodoItem, index: number) => {
            ListItem() {
              Row({ space: 12 }) {
                // 完成状态勾选框
                Checkbox({ name: `todo_${item.id}` })
                  .select(item.done)
                  .onChange((value: boolean) => {
                    this.toggleTodo(item.id);
                  })

                // 文字
                Text(item.text)
                  .fontSize(16)
                  .fontColor(item.done ? '#CCC' : '#333')
                  .decoration({
                    type: item.done ? TextDecorationType.LineThrough : TextDecorationType.None
                  })
                  .layoutWeight(1)

                // 删除按钮
                Button('删除')
                  .fontSize(13)
                  .fontColor('#FF3B30')
                  .backgroundColor('#FFF')
                  .onClick(() => {
                    this.deleteTodo(item.id);
                  })
              }
              .width('100%')
              .padding(12)
            }
          },
          (item: TodoItem) => item.id.toString()
        )
      }
      .layoutWeight(1)
      .divider({ strokeWidth: 0.5, color: '#EEE' })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FAFAFA')
  }
}

8.2 功能说明

  • 添加:输入文字点击"添加",追加到列表头部
  • 完成:勾选复选框,文字变灰 + 删除线
  • 删除:点击红色"删除"按钮,从列表移除
  • 统计:顶部实时显示总数和已完成数

九、总结

核心知识点回顾

层级 知识点
语言基础 类型标注、接口、类、枚举、箭头函数
UI 框架 @Entry@Componentbuild()、链式属性
布局 Column / Row / Flex
组件 Text、Image、Button、TextInput、List、Scroll
渲染 if/else 条件渲染、ForEach 循环渲染
状态 @State@Prop@Link@Provide/@Consume
路由 router.pushUrl()router.back()、参数传递

学习路线建议

  1. 第 1 天:搭环境,跑通 Hello World,熟悉 DevEco Studio
  2. 第 2-3 天:写 5-10 个简单页面,把常用组件都用一遍
  3. 第 4-5 天:深入状态管理,尤其是 @State / @Link 的组合用法
  4. 第 6-7 天:做一个完整的小应用(Todo、天气、计数器等)
  5. 第 2 周起:学习网络请求(@ohos.net.http)、本地存储、真机调试

推荐资源


写在最后:ArkTS 的学习曲线对前端开发者非常友好。如果你有 Vue/React 的经验,会发现声明式 UI + 状态管理的模式和它们非常相似,上手基本没有障碍。对于原生开发(Android/iOS)的同学,声明式 UI 可能需要一点思维转变,但一旦适应,开发效率会大幅提升。


本文原创发布于 CSDN,转载请注明出处。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐