【OpenHarmony北向开发】ArkTS基础教学

面向 HarmonyOS 应用开发的 ArkTS 语言从入门到实战,涵盖完整语法 + 声明式 UI + 综合案例。


文章目录

  • [1. ArkTS 是什么](#1. ArkTS 是什么)
  • [2. 开发环境与第一个程序](#2. 开发环境与第一个程序)
  • [3. 变量与数据类型](#3. 变量与数据类型)
  • [4. 运算符与表达式](#4. 运算符与表达式)
  • [5. 字符串](#5. 字符串)
  • [6. 条件与循环](#6. 条件与循环)
  • [7. 函数](#7. 函数)
  • [8. 数组与集合](#8. 数组与集合)
  • [9. 对象与接口](#9. 对象与接口)
  • [10. 类与面向对象](#10. 类与面向对象)
  • [11. 泛型](#11. 泛型)
  • [12. 声明式 UI 基础(ArkUI)](#12. 声明式 UI 基础(ArkUI))
  • [13. 状态管理](#13. 状态管理)
  • [14. 事件处理与常用组件](#14. 事件处理与常用组件)
  • [15. 综合案例:TodoList 待办应用](#15. 综合案例:TodoList 待办应用)
  • 附录:学习路线建议

1. ArkTS 是什么

ArkTS 是华为专为 HarmonyOS 开发的一门语言,它在 TypeScript(TS) 的基础上做了严格化和扩展,核心特点:

  • 静态类型强约束 :不允许 any 随便乱飞,编译期就能发现类型错误,适合大型工程。
  • 声明式 UI 范式:用类似"描述界面长什么样"的方式写 UI,数据变了界面自动刷新。
  • 响应式状态管理 :通过 @State、@Link 等装饰器,把数据和界面绑定起来。
  • 禁止动态特性 :不支持 eval()、不允许随意 delete 属性、不允许用索引访问任意字段,目的是提升性能和稳定性。

一句话理解:ArkTS = 严格版 TypeScript + 鸿蒙专属的 UI 框架。如果你学过 TS,迁移非常快;如果没学过 TS,按本教程走也没问题。


2. 开发环境与第一个程序

2.1 环境准备

  1. 安装 DevEco Studio(华为官方 IDE,类似 Android Studio)。
  2. 创建新项目时选择 Empty Ability ,语言选 ArkTS。
  3. 项目核心代码在 entry/src/main/ets/ 目录下。

2.2 第一个 Hello World

打开 entry/src/main/ets/pages/Index.ets,默认代码如下:

typescript 复制代码
@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Hello World')
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

逐行解释:

代码 作用
@Entry 标记这是页面入口组件(一个页面只能有一个)
@Component 标记这是一个 UI 组件,可以被复用
struct Index 定义一个结构体(ArkTS 用 struct 写组件)
build() 必须实现的方法,描述这个组件长什么样
Column() 线性布局,子元素竖向排列
Text('Hello World') 文本组件
.fontSize(30) 链式调用设置样式

点击运行按钮,模拟器上就能看到居中的 "Hello World"。


3. 变量与数据类型

3.1 声明变量

ArkTS 只允许用 let 和 const ,禁止使用 var。

typescript 复制代码
let name: string = '小明'        // 可变变量
const PI: number = 3.14159       // 常量,不能重新赋值
let age = 20                      // 类型自动推导为 number
  • let:变量值可以改。
  • const:常量,声明时必须赋值,之后不能改。
  • 推荐:默认用 const,确定要改才用 let。

3.2 基本数据类型

类型 说明 示例
number 数字(整数和小数都是它) 42、3.14、-7
string 字符串 '你好'、"hello"
boolean 布尔值 true、false
null 空值 null
undefined 未定义 undefined
void 函数无返回值 function f(): void {}

3.3 类型注解

typescript 复制代码
let score: number = 95
let username: string = 'zhangsan'
let isPass: boolean = true

类型注解是可选的------编译器会自动推导,但写上更清晰,大型项目建议显式标注。

3.4 联合类型

一个变量可以是多种类型之一:

typescript 复制代码
let id: number | string
id = 100          // OK
id = 'A001'       // OK
// id = true      // 报错,boolean 不在联合类型里

3.5 字面量类型

限定变量只能取某个具体值:

typescript 复制代码
let direction: 'up' | 'down' | 'left' | 'right'
direction = 'up'      // OK
// direction = 'back'  // 报错

4. 运算符与表达式

4.1 算术运算符

typescript 复制代码
let a: number = 10
let b: number = 3

a + b    // 13
a - b    // 7
a * b    // 30
a / b    // 3.333...
a % b    // 1(取余)
a ** b   // 1000(幂运算)

4.2 比较运算符

typescript 复制代码
5 > 3       // true
5 >= 5      // true
5 < 3       // false
5 == '5'    // false(ArkTS 严格相等,类型不同直接 false)
5 === 5     // true(推荐用 === 和 !==)
5 != '5'    // true
5 !== 5     // false

注意 :ArkTS 没有 == 的隐式转换,推荐始终用 === 和 !==。

4.3 逻辑运算符

typescript 复制代码
true && false    // false(与)
true || false    // true(或)
!true            // false(非)

4.4 赋值运算符

typescript 复制代码
let x: number = 10
x += 5     // x = 15
x -= 3     // x = 12
x *= 2     // x = 24
x /= 4     // x = 6

4.5 三元运算符

typescript 复制代码
let age: number = 20
let result: string = age >= 18 ? '成年' : '未成年'

5. 字符串

5.1 多种写法

typescript 复制代码
let s1: string = '单引号'
let s2: string = "双引号"
let s3: string = `模板字符串`

5.2 模板字符串(重点)

用反引号 ````` 包裹,可以嵌入变量:

typescript 复制代码
let name: string = '小红'
let age: number = 18
let msg: string = `我叫${name},今年${age}岁`
// 我叫小红,今年18岁

还支持换行:

typescript 复制代码
let poem: string = `床前明月光,
疑是地上霜。`

5.3 常用方法

typescript 复制代码
let str: string = 'Hello ArkTS'

str.length              // 11
str.toUpperCase()       // 'HELLO ARKTS'
str.toLowerCase()       // 'hello arkts'
str.indexOf('Ark')      // 6
str.substring(6, 11)    // 'ArkTS'
str.split(' ')          // ['Hello', 'ArkTS']
str.replace('Ark', 'Harmony')  // 'Hello HarmonyTS'
str.trim()              // 去除首尾空格

6. 条件与循环

6.1 if / else

typescript 复制代码
let score: number = 85

if (score >= 90) {
  console.log('优秀')
} else if (score >= 80) {
  console.log('良好')
} else if (score >= 60) {
  console.log('及格')
} else {
  console.log('不及格')
}

6.2 switch

typescript 复制代码
let day: number = 3
switch (day) {
  case 1:
    console.log('周一')
    break
  case 2:
    console.log('周二')
    break
  case 3:
    console.log('周三')
    break
  default:
    console.log('其他')
}

6.3 for 循环

typescript 复制代码
// 经典 for
for (let i: number = 0; i < 5; i++) {
  console.log(i)    // 0 1 2 3 4
}

6.4 for...of(遍历数组)

typescript 复制代码
let fruits: string[] = ['苹果', '香蕉', '橙子']
for (let fruit of fruits) {
  console.log(fruit)
}

6.5 while 循环

typescript 复制代码
let count: number = 3
while (count > 0) {
  console.log(count)
  count--
}

7. 函数

7.1 函数声明

typescript 复制代码
function add(a: number, b: number): number {
  return a + b
}

let sum: number = add(3, 5)   // 8

括号里 a: number 是参数类型,: number 在括号后面是返回值类型。

7.2 箭头函数(常用)

typescript 复制代码
const multiply = (a: number, b: number): number => {
  return a * b
}

// 单行可以省略 return 和大括号
const square = (x: number): number => x * x

7.3 参数默认值

typescript 复制代码
function greet(name: string, greeting: string = '你好'): string {
  return `${greeting},${name}`
}

greet('小明')           // '你好,小明'
greet('小红', '早上好')   // '早上好,小红'

7.4 可选参数

用 ? 标记可选参数:

typescript 复制代码
function buildName(first: string, last?: string): string {
  if (last) {
    return `${first} ${last}`
  }
  return first
}

buildName('张')        // '张'
buildName('张', '三')   // '张 三'

7.5 无返回值

typescript 复制代码
function logMessage(msg: string): void {
  console.log(msg)
}

8. 数组与集合

8.1 数组声明与初始化

typescript 复制代码
let nums: number[] = [1, 2, 3, 4, 5]
let names: Array<string> = ['Tom', 'Jerry']
let empty: number[] = []

8.2 常用操作

typescript 复制代码
let arr: number[] = [10, 20, 30]

arr.push(40)         // 末尾添加:[10,20,30,40]
arr.pop()            // 末尾删除:返回 40
arr.unshift(5)       // 开头添加:[5,10,20,30]
arr.shift()          // 开头删除:返回 5
arr.length           // 长度
arr[0]               // 访问第一个元素
arr.indexOf(20)      // 查找索引

8.3 数组遍历方法(重点)

typescript 复制代码
let numbers: number[] = [1, 2, 3, 4, 5]

// forEach:遍历
numbers.forEach((n: number) => {
  console.log(n)
})

// map:映射成新数组
let doubled: number[] = numbers.map((n: number): number => n * 2)
// [2, 4, 6, 8, 10]

// filter:过滤
let evens: number[] = numbers.filter((n: number): boolean => n % 2 === 0)
// [2, 4]

// reduce:汇总
let total: number = numbers.reduce((sum: number, n: number): number => sum + n, 0)
// 15

// find:查找第一个满足条件的
let firstBig: number | undefined = numbers.find((n: number): boolean => n > 3)
// 4

8.4 Set(不重复集合)

typescript 复制代码
let set: Set<number> = new Set([1, 2, 2, 3, 3, 3])
// Set {1, 2, 3}
set.add(4)
set.has(2)      // true
set.delete(1)
set.size        // 3

8.5 Map(键值对)

typescript 复制代码
let map: Map<string, number> = new Map()
map.set('语文', 90)
map.set('数学', 95)

map.get('语文')     // 90
map.has('数学')     // true
map.delete('语文')
map.size            // 1

九、对象与接口

9.1 接口(interface)------ ArkTS 核心

接口用来描述对象的结构:

typescript 复制代码
interface User {
  name: string
  age: number
  email?: string      // 可选属性
}

let user: User = {
  name: '小明',
  age: 20,
  email: 'xiao@test.com'
}

console.log(user.name)    // 小明

接口是 ArkTS 中最常用的类型定义方式,用来规范数据结构,配合 UI 组件传参非常方便。

9.2 type 别名

typescript 复制代码
type Point = {
  x: number
  y: number
}

let p: Point = { x: 10, y: 20 }

接口和 type 大部分场景可互换,推荐对象结构用 interface,联合类型/别名用 type。

9.3 接口继承

typescript 复制代码
interface Animal {
  name: string
}

interface Dog extends Animal {
  breed: string
}

let myDog: Dog = {
  name: '旺财',
  breed: '金毛'
}

十、类与面向对象

10.1 定义类

typescript 复制代码
class Person {
  name: string
  age: number

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

  sayHello(): void {
    console.log(`你好,我叫${this.name},今年${this.age}岁`)
  }
}

let p: Person = new Person('小明', 20)
p.sayHello()    // 你好,我叫小明,今年20岁

10.2 访问修饰符

修饰符 说明
public 公开(默认),内外都能访问
private 私有,只有类内部能访问
protected 保护,类内部和子类能访问
typescript 复制代码
class Account {
  public owner: string
  private balance: number

  constructor(owner: string, balance: number) {
    this.owner = owner
    this.balance = balance
  }

  deposit(amount: number): void {
    this.balance += amount
  }

  getBalance(): number {
    return this.balance
  }
}

let acc: Account = new Account('张三', 1000)
acc.deposit(500)
console.log(acc.getBalance())   // 1500
// console.log(acc.balance)     // 报错,private 不能外部访问

10.3 继承

typescript 复制代码
class Student extends Person {
  school: string

  constructor(name: string, age: number, school: string) {
    super(name, age)    // 调用父类构造函数
    this.school = school
  }

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

let s: Student = new Student('小红', 19, '西安电子科技大学')
s.sayHello()    // 继承自父类
s.study()       // 自己的方法

10.4 static 静态成员

typescript 复制代码
class Calculator {
  static PI: number = 3.14159

  static circleArea(radius: number): number {
    return Calculator.PI * radius * radius
  }
}

console.log(Calculator.circleArea(5))   // 78.53975

10.5 getter / setter

typescript 复制代码
class Rectangle {
  private _width: number = 0
  private _height: number = 0

  set width(w: number) {
    if (w > 0) {
      this._width = w
    }
  }

  get width(): number {
    return this._width
  }

  get area(): number {
    return this._width * this._height
  }
}

十一、泛型

泛型就是"类型的参数",让函数/类可以适配多种类型而不丢失类型检查。

11.1 泛型函数

typescript 复制代码
function identity<T>(arg: T): T {
  return arg
}

let n: number = identity<number>(42)
let str: string = identity<string>('hello')

11.2 泛型接口

typescript 复制代码
interface Result<T> {
  code: number
  data: T
  message: string
}

let r1: Result<string> = { code: 200, data: '成功', message: 'OK' }
let r2: Result<number[]> = { code: 200, data: [1, 2, 3], message: 'OK' }

11.3 泛型类

typescript 复制代码
class Stack<T> {
  private items: T[] = []

  push(item: T): void {
    this.items.push(item)
  }

  pop(): T | undefined {
    return this.items.pop()
  }
}

let numStack: Stack<number> = new Stack<number>()
numStack.push(1)
numStack.push(2)

十二、声明式 UI 基础(ArkUI)

ArkTS 的核心是 ArkUI 声明式开发范式。界面由组件组合而成。

12.1 核心概念

  • 组件(Component) :UI 的基本单元,如 Text、Button、Image。
  • 布局容器 :控制子组件如何排列,如 Column、Row、Stack、Flex。
  • build() 函数:描述组件 UI 的入口。

12.2 常用基础组件

typescript 复制代码
@Entry
@Component
struct BasicsPage {
  build() {
    Column({ space: 10 }) {
      // 文本
      Text('你好,ArkTS')
        .fontSize(24)
        .fontColor('#333333')

      // 按钮
      Button('点击我')
        .type(ButtonType.Capsule)
        .width(150)
        .height(40)

      // 图片
      Image('https://example.com/icon.png')
        .width(60)
        .height(60)

      // 输入框
      TextInput({ placeholder: '请输入内容' })
        .width('90%')
        .height(45)
    }
    .width('100%')
    .padding(16)
  }
}

12.3 布局容器

Column(竖向排列)
typescript 复制代码
Column({ space: 12 }) {
  Text('第一行')
  Text('第二行')
  Text('第三行')
}
.width('100%')
.alignItems(HorizontalAlign.Center)   // 子元素水平居中
Row(横向排列)
typescript 复制代码
Row({ space: 16 }) {
  Text('左')
  Text('中')
  Text('右')
}
.width('100%')
.justifyContent(FlexAlign.SpaceEvenly)  // 子元素均匀分布
Stack(层叠布局)
typescript 复制代码
Stack({ alignContent: Alignment.BottomCenter }) {
  Image('bg.jpg').width(200).height(200)
  Text('覆盖在上面的文字')
    .fontColor(Color.White)
}

12.4 通用样式属性

typescript 复制代码
Text('样式演示')
  .width(200)
  .height(50)
  .backgroundColor('#F0F0F0')
  .borderRadius(8)
  .padding(10)
  .margin({ top: 10, bottom: 10 })
  .textAlign(TextAlign.Center)

十三、状态管理

状态管理是 ArkTS 声明式 UI 的灵魂:数据变了,界面自动刷新。

13.1 @State(组件内状态)

@State 修饰的变量变化时,UI 自动重新渲染:

typescript 复制代码
@Entry
@Component
struct CounterPage {
  @State count: number = 0    // 状态变量

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

      Button('+1')
        .onClick(() => {
          this.count++      // 修改状态 → 界面自动刷新
        })

      Button('重置')
        .onClick(() => {
          this.count = 0
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

关键点 :只要 this.count 变了,Text 组件就会自动重新渲染,你不需要手动操作 DOM。

13.2 @Prop(父传子,单向)

父组件传给子组件的数据,子组件只读:

typescript 复制代码
// 子组件
@Component
struct ChildText {
  @Prop message: string    // 接收父组件传入的值

  build() {
    Text(this.message).fontSize(20)
  }
}

// 父组件
@Entry
@Component
struct ParentPage {
  @State parentMsg: string = '来自爸爸的消息'

  build() {
    Column() {
      ChildText({ message: this.parentMsg })
    }
  }
}

13.3 @Link(父子双向绑定)

父子组件共享同一份数据,任意一方修改都同步:

typescript 复制代码
@Component
struct CounterChild {
  @Link count: number    // 双向绑定

  build() {
    Button('子组件 +1')
      .onClick(() => {
        this.count++     // 修改会同步回父组件
      })
  }
}

@Entry
@Component
struct CounterParent {
  @State count: number = 0

  build() {
    Column({ space: 20 }) {
      Text(`父组件计数:${this.count}`).fontSize(24)
      CounterChild({ count: $count })    // 注意 $ 符号表示双向绑定
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

13.4 @Builder(自定义 UI 片段)

把重复的 UI 抽成模板:

typescript 复制代码
@Entry
@Component
struct BuilderPage {
  @State title: string = '卡片标题'

  @Builder
  card(title: string, content: string) {
    Column() {
      Text(title).fontSize(18).fontWeight(FontWeight.Bold)
      Text(content).fontSize(14).fontColor('#666')
    }
    .width('90%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(12)
  }

  build() {
    Column({ space: 12 }) {
      this.card('通知', '你有一条新消息')
      this.card('提醒', '记得喝水')
    }
    .width('100%')
    .backgroundColor('#F5F5F5')
    .padding(16)
  }
}

十四、事件处理与常用组件

14.1 点击事件

typescript 复制代码
Button('按钮')
  .onClick(() => {
    console.log('按钮被点击了')
  })

14.2 输入框与状态绑定

typescript 复制代码
@Entry
@Component
struct InputPage {
  @State inputText: string = ''

  build() {
    Column({ space: 16 }) {
      TextInput({ text: this.inputText, placeholder: '请输入' })
        .width('90%')
        .height(45)
        .onChange((value: string) => {
          this.inputText = value    // 输入内容实时同步到状态
        })

      Text(`你输入了:${this.inputText}`)
        .fontSize(18)
    }
    .width('100%')
    .padding(16)
  }
}

14.3 List 列表(高频使用)

typescript 复制代码
@Entry
@Component
struct ListPage {
  @State todos: string[] = ['学习 ArkTS', '写作业', '健身', '买水果']

  build() {
    Column() {
      Text('待办列表').fontSize(22).fontWeight(FontWeight.Bold)

      List({ space: 10 }) {
        ForEach(this.todos, (item: string, index: number) => {
          ListItem() {
            Text(`${index + 1}. ${item}`)
              .fontSize(18)
              .padding(12)
              .width('100%')
              .backgroundColor(Color.White)
              .borderRadius(8)
          }
        })
      }
      .width('90%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .padding(16)
    .backgroundColor('#F5F5F5')
  }
}

ForEach 是列表渲染的核心,类似 React 的 map,根据数组生成重复组件。


十五、综合案例:TodoList 待办应用

把前面学的所有知识整合起来,做一个完整的待办事项应用:支持添加、完成、删除任务。

typescript 复制代码
// 数据模型
interface Todo {
  id: number
  text: string
  completed: boolean
}

@Entry
@Component
struct TodoListApp {
  // 状态
  @State newTask: string = ''
  @State todoList: Todo[] = [
    { id: 1, text: '学习 ArkTS 基础语法', completed: true },
    { id: 2, text: '完成布局练习', completed: false },
    { id: 3, text: '写综合案例', completed: false }
  ]
  private nextId: number = 4

  // 统计完成数
  get completedCount(): number {
    return this.todoList.filter((t: Todo): boolean => t.completed).length
  }

  // 添加任务
  addTask(): void {
    if (this.newTask.trim().length === 0) {
      return
    }
    let task: Todo = {
      id: this.nextId++,
      text: this.newTask.trim(),
      completed: false
    }
    this.todoList.push(task)
    this.newTask = '' // 清空输入框
  }

  // 切换完成状态
  toggleTask(id: number): void {
    this.todoList = this.todoList.map((item: Todo): Todo => {
      if (item.id === id) {
        return {
          id: item.id,
          text: item.text,
          completed: !item.completed
        }
      }
      return item
    })
  }

  // 删除任务
  deleteTask(id: number): void {
    this.todoList = this.todoList.filter((item: Todo): boolean => item.id !== id)
  }

  build() {
    Column() {
      // 标题
      Text('我的待办')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ top: 20, bottom: 10 })

      // 统计
      Text(`共 ${this.todoList.length} 项,已完成 ${this.todoList.filter((t: Todo): boolean => t.completed).length} 项`)
        .fontSize(14)
        .fontColor('#888888')
        .margin({ bottom: 16 })

      // 输入区域
      Row({ space: 10 }) {
        TextInput({ text: this.newTask, placeholder: '输入新任务...' })
          .layoutWeight(1)
          .height(45)
          .backgroundColor(Color.White)
          .borderRadius(8)
          .onChange((value: string) => {
            this.newTask = value
          })
          .onSubmit(() => {
            this.addTask()
          })

        Button('添加')
          .height(45)
          .onClick(() => {
            this.addTask()
          })
      }
      .width('90%')
      .margin({ bottom: 16 })

      // 任务列表
      List({ space: 10 }) {
        ForEach(this.todoList, (item: Todo) => {
          ListItem() {
            Row() {
              // 完成标记圆圈
              Text(item.completed ? '✓' : ' ')
                .fontSize(16)
                .fontColor(Color.White)
                .width(26)
                .height(26)
                .textAlign(TextAlign.Center)
                .borderRadius(13)
                .backgroundColor(item.completed ? '#4CAF50' : '#CCCCCC')
                .onClick(() => {
                  this.toggleTask(item.id)
                })

              // 任务文字
              Text(item.text)
                .fontSize(16)
                .layoutWeight(1)
                .margin({ left: 12 })
                .fontColor(item.completed ? '#AAAAAA' : '#333333')
                .decoration({ type: item.completed ? TextDecorationType.LineThrough : TextDecorationType.None })

              // 删除按钮
              Text('✕')
                .fontSize(18)
                .fontColor('#FF5252')
                .width(30)
                .onClick(() => {
                  this.deleteTask(item.id)
                })
            }
            .width('100%')
            .padding(12)
            .backgroundColor(Color.White)
            .borderRadius(8)
          }
        }, (item: Todo) => `${item.id}-${item.completed}`)
      }
      .width('90%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

案例知识点回顾

知识点 在案例中的体现
interface 定义 Todo 数据结构
@State 管理 newTask、todoList 状态
@Entry / @Component 页面入口组件
Column / Row 整体布局
TextInput / Button / Text 基础组件
List + ForEach 渲染任务列表
箭头函数 事件处理回调
数组 map / filter 修改和删除任务
模板字符串 统计文本拼接
三元运算符 条件样式判断
getter completedCount 计算属性

附录:学习路线建议

复制代码
基础语法(变量/类型/函数)
    ↓
面向对象(类/接口/泛型)
    ↓
ArkUI 声明式布局(Column/Row/List)
    ↓
状态管理(@State/@Prop/@Link)
    ↓
实战项目(TodoList → 天气App → 网络请求)
    ↓
进阶(路由导航、网络请求、持久化存储、自定义组件)

练习建议 :把上面的 TodoList 案例亲手敲一遍,然后尝试扩展------加个"全部/未完成/已完成"筛选标签、加数据持久化(@StorageProp 或首选项),就是一个完整的上线级小应用了。

相关推荐
ZoeLandia3 小时前
TypeScript 01:类型注解与类型推断
前端·javascript·typescript
ZoeLandia4 小时前
TypeScript 02:interface、type 与类型收窄
前端·typescript
行者-全栈开发5 小时前
华为云码道 CodeArts 实测:让 AI 用纯 TypeScript 写一个确定性回放的塔防小游戏「熵减特勤局」
typescript·小游戏·canvas·ecs·ai 编程·华为云码道·codearts 代码智能体
mbshqqb1 天前
TypeScript基础教程之同步生成器
前端·javascript·typescript
濮水大叔2 天前
Cabloy 双引擎架构详解:Vona 与 Zova 是如何协作的
typescript·node.js·全栈
前端大斗师2 天前
「大于 1000」把 1000 元那单也算进去了:我在 Vue3 订单页对了 10 句话
前端·人工智能·typescript·大模型·原力计划
GlobalAIagent2 天前
外贸站上线前的技术自查清单:漏一项询盘可能消失
google·typescript·ar·go语言·seo
半糖程序员2 天前
从零构建 Agent(11):压缩过长的上下文
typescript·agent
whi2 天前
一个小工具,解决了一个困扰 Vue 开发者多年的类型检查难题
vue.js·typescript