你真以为“ArkTS = TypeScript 换皮”?那为什么你一写就踩坑呢

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8
🤨 摘要
说真的,我第一次接触 ArkTS 的时候,内心是有点飘的:“TypeScript 我熟啊,ArkTS 不就是换个名字嘛~”
结果呢?写着写着我就开始怀疑人生:类型怎么更“较真”了、装饰器怎么更“有脾气”了、声明式 UI 写得爽是爽,但状态一乱 UI 就像闹情绪一样不听话🙃
所以这篇我就不端着讲“语法大全”了(那太像说明书了😅),咱用**“对比 + 场景 + 可跑的代码”**把 ArkTS 的基础语法一次捋顺,顺便把你未来最容易踩的坑提前铲平🧹✨
🧭目录(先把路标插上,不然容易迷路🤣)
- 🥊 ArkTS vs TypeScript:到底“像”在哪,“不一样”又在哪?
- 🧩 声明式语法:不是写 UI,更像在“描述状态”😏
- 🧬 类型系统:ArkTS 的“严谨”会逼你变强💪
- 🧱 变量 / 函数 / 类:基础语法但别掉以轻心😵
- ⏳ 异步编程:Promise / async-await 的正确姿势🤺
- 🎀 装饰器:@State/@Prop/@Link 这些“神仙符号”到底干啥?
- 🕳️ 高频坑位合集:我替你先踩了,真的😭
🥊 ArkTS vs TypeScript:到底“像”在哪,“不一样”又在哪?
先给结论,别吊你胃口😄:
✅ 像:
- 语法大体基于 TypeScript:
let/const、类型标注、接口、泛型、类、模块化……这些你都能无痛上手😎 - 开发体验上也偏“工程化”:类型约束强、IDE 友好、可维护性强✨
⚠️ 不一样(重点来了,别眨眼👀):
- ArkTS 是为鸿蒙场景“定制强化”的:在 UI 声明式、状态管理、运行时约束等方面更“规矩”
- 在 ArkUI 里,装饰器 + 状态驱动 UI是核心玩法,不是“语法糖”
- 某些写法在 TS 里你能糊弄过去,在 ArkTS 里它会直接跟你说:不行!🙅(像极了严格的班主任🤣)
一句话总结:
TypeScript 像“通用语”,ArkTS 像“鸿蒙方言 + 规章制度”。
你会说方言不难,难的是规章制度——不遵守就扣分😅
🧩 声明式语法:不是写 UI,更像在“描述状态”😏
声明式的精髓是:
UI = f(state)
也就是:界面长啥样,是状态决定的;你别老想着“我去改某个控件”,你要想着“我改状态,让界面自己变”。
✅ 一个最小但很典型的例子(看完秒懂)
@Entry
@Component
struct DemoDeclarative {
@State count: number = 0
build() {
Column() {
Text(`😄 当前计数:${this.count}`)
.fontSize(20)
.margin({ bottom: 12 })
Button('➕ 点我+1')
.onClick(() => {
this.count += 1
})
}
.padding(20)
}
}
你看这里根本没有“找到某个 Text 然后 setText()”这种命令式操作。
你只管改 count,UI 自己更新。
这就是声明式的爽点:少操心,多快乐😆
🧬 类型系统:ArkTS 的“严谨”会逼你变强💪
我个人对 ArkTS 类型系统的感受是:
它像一个嘴很碎但很靠谱的队友:你写错它立刻提醒你,烦是烦,但能救命😂
1)基础类型(但别小看)
let name: string = 'Harmony'
let age: number = 18
let ok: boolean = true
let list: number[] = [1, 2, 3]
let pair: [string, number] = ['🍅', 3]
2)联合类型:灵活但要收敛(不然你自己也懵😵)
type ID = string | number
function printId(id: ID) {
if (typeof id === 'string') {
console.info(`string id = ${id.toUpperCase()}`)
} else {
console.info(`number id = ${id.toFixed(0)}`)
}
}
3)可选与空值:别偷懒,写清楚!
interface User {
name: string
nickname?: string
}
function show(user: User) {
const nick = user.nickname ?? '😅 没昵称'
console.info(`${user.name} / ${nick}`)
}
我建议你养成习惯:
能确定的类型就写死,可能为空就显式处理。
别靠“侥幸心理”,因为线上 bug 从不讲武德🤺
🧱 变量 / 函数 / 类:基础语法但别掉以轻心😵
1)变量:const 能用就别 let(克制是一种美德🥹)
const MAX_RETRY: number = 3
let retry: number = 0
retry += 1
2)函数:参数默认值 + 返回类型,写起来更稳
function greet(name: string = '朋友'): string {
return `👋 你好呀,${name}!`
}
3)类:封装数据与行为(别把一堆逻辑堆页面里🙏)
class Counter {
private value: number = 0
inc(step: number = 1): number {
this.value += step
return this.value
}
get(): number {
return this.value
}
}
const c = new Counter()
console.info(`count=${c.inc()}`) // 1
我最怕看到的一种项目是:
页面里又是网络、又是存储、又是业务规则……
写起来短期爽,维护起来像在拆炸弹💣😭
⏳ 异步编程:Promise / async-await 的正确姿势🤺
鸿蒙开发里异步非常常见:
- 读写本地数据
- 网络请求
- 系统能力调用
你要是异步写乱了,UI 就会出现:卡顿、顺序错乱、偶现 bug,最气人的是——还不好复现😤
1)Promise 基础:链式写法(可用,但别写成“意大利面”🍝)
function delay(ms: number): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => resolve(`⏱ 等了 ${ms}ms`), ms)
})
}
delay(500)
.then(res => console.info(res))
.catch(err => console.error(err))
2)async/await:更像同步代码(强烈推荐👍)
async function runTask() {
try {
const a = await delay(300)
const b = await delay(200)
console.info(`✅ done: ${a}, ${b}`)
} catch (e) {
console.error(`💥 出错了:${JSON.stringify(e)}`)
}
}
3)并发:别傻等,一个 Promise.all 就很香😋
async function runParallel() {
const [a, b] = await Promise.all([delay(300), delay(300)])
console.info(`🚀 parallel: ${a} | ${b}`)
}
我送你一句很“现实”的话:
能并发就并发,能超时就超时,能兜底就兜底。
不然用户一差评,你就知道什么叫“社会的毒打”🥲
🎀 装饰器:@State/@Prop/@Link 这些“神仙符号”到底干啥?
装饰器在 ArkUI 里不是花里胡哨,它是状态管理的核心机制。
你可以把它理解成:
“我给这份数据贴了个标签,框架就知道该怎么追踪它、更新它、传递它。”
听着玄?不玄,来,上代码😄
1)@State:组件内部状态(UI 的“情绪开关”😏)
@Entry
@Component
struct StateDemo {
@State msg: string = '🙂 我还挺正常的'
build() {
Column() {
Text(this.msg).fontSize(18).margin({ bottom: 10 })
Button('😈 让我变个脸')
.onClick(() => this.msg = '😤 我现在有点暴躁了')
}.padding(20)
}
}
2)@Prop:父传子(子组件别乱改,老老实实接收🙇)
@Component
struct ChildProp {
@Prop title: string
build() {
Text(`📦 子组件收到:${this.title}`)
}
}
@Entry
@Component
struct ParentProp {
@State title: string = '来自父组件的爱💖'
build() {
Column() {
ChildProp({ title: this.title })
Button('✏️ 父组件改一下')
.onClick(() => this.title = '父组件更新啦✨')
}.padding(20)
}
}
3)@Link:双向绑定(父子一起改,像“共同财产”🤣)
@Component
struct ChildLink {
@Link count: number
build() {
Row() {
Button('➖').onClick(() => this.count -= 1)
Text(` ${this.count} `).fontSize(18).margin({ left: 8, right: 8 })
Button('➕').onClick(() => this.count += 1)
}
}
}
@Entry
@Component
struct ParentLink {
@State count: number = 1
build() {
Column() {
Text(`🏠 父组件:${this.count}`).margin({ bottom: 10 })
ChildLink({ count: $count })
}.padding(20)
}
}
看到 $count 没?这就是把父组件的状态“链接”出去。
子组件一改,父组件立刻同步。
但我也得提醒一句:双向绑定很爽,也很容易滥用😅
- 小范围交互用它很香
- 复杂业务别全靠 Link,不然状态流像蜘蛛网🕸️,你以后 debug 会哭😭
🕳️ 高频坑位合集:我替你先踩了,真的😭
-
😵 “我改了对象属性,为啥 UI 不刷新?”
很可能你在原地 mutate。解决:用新对象替换,或调整状态结构,让框架可感知变化。 -
🤯 异步请求回来晚了,把新状态覆盖成旧状态
解决:加请求序号/时间戳,或做取消机制,别让“过期响应”乱入。 -
🥲 组件拆分后,@Prop/@Link 用错导致数据不同步
记住:- @Prop:单向
- @Link:双向
不要“想当然”瞎贴标签😂
-
🧨 Promise 链写太长,异常处理漏了
用 async/await + try/catch,基本能救你一命。
🧷最后我再“碎嘴”一句(真心的😄)
ArkTS 学起来不难,难的是把思维从“命令式”扭到“声明式”。
你只要把这句话刻进脑子里:
“我不操作 UI,我只操作状态;UI 是状态的投影。”
后面写起来会越来越顺,顺到你会想:
“以前我到底在手动 setText 干嘛呀?!”🤣
🧧福利赠与你🧧
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。
✨️ Who am I?
我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-
- 点赞
- 收藏
- 关注作者
评论(0)