HarmonyOS APP《画伴梦工厂》开发第1篇:ArkTS 语言入门——从 TypeScript 到 ArkTS
第1篇ArkTS 语言入门——从 TypeScript 到 ArkTS系列鸿蒙 ArkTS 与 ArkUI 基础篇难度⭐ 入门前置知识TypeScript 基础一、为什么是 ArkTSArkTS 是华为为 HarmonyOS 应用开发量身定制的编程语言基于 TypeScript 扩展而来。它保留了 TypeScript 的类型系统和现代 JavaScript 语法同时引入了装饰器语法和声明式 UI 能力让开发者能用更少的代码写出更健壮的应用。与标准 TypeScript 相比ArkTS 有以下核心差异对比维度TypeScriptArkTS类型检查编译时 运行时可选强制编译时检查禁止隐式 any装饰器实验性支持(experimentalDecorators)一等公民Component/State/Builder 等UI 渲染无内置 UI 框架声明式 UI 框架与 build() 方法深度绑定并发模型Promise/async-await支持 TaskPool/Worker 并发动态特性允许宽松模式严格模式禁止动态属性访问二、ArkTS 的装饰器体系ArkTS 最显著的特征是装饰器语法。在画伴梦工厂项目中几乎每个文件都会用到装饰器。来看 Index.ets 中最核心的装饰器用法Entry Component声明页面组件EntryComponentstruct Index{// 组件的状态和UI逻辑build(){// 声明式UI描述}}Entry标记当前组件是一个页面入口。被Entry装饰的组件会自动获得页面生命周期aboutToAppear、aboutToDisappear、onPageShow、onPageHide。Component声明这是一个自定义组件。组件内部必须实现build()方法描述 UI 结构。structArkTS 组件基于结构体struct定义而非类class。这是因为 ArkTS 中组件是值类型结构体的值语义更适合 UI 组件的不可变数据流。与标准的 TypeScript 差异TypeScript 中没有Component这样的框架装饰器。ArkTS 将装饰器作为语言核心特性而非实验性功能。State响应式状态驱动EntryComponentstruct Index{StorageLink(mainBreakpoint)currentBreakpoint:stringmd;StateprivatecurrentTab:number0;StateprivatesecondaryPage:numberSECONDARY_NONE;StateprivategenerationProgress:number68;StateprivateisPlaying:booleantrue;StateprivatechatInput:string;StateprivatechatMessages:ChatMessage[][{id:1,role:assistant,text:说出你想创作的角色和场景...,imageUri:}];// ... 总共约30个 State 变量}State是 ArkTS 响应式状态管理的核心。当State变量的值发生变化时依赖该变量的 UI 会自动重新渲染。项目中 Index.ets 使用了约 30 个State变量来管理不同的 UI 状态——从当前 Tab 页、视频播放状态、聊天记录到画笔设置等。Builder声明式 UI 复用BuilderprivateheroBanner(){Stack(){// 英雄区域背景和内容}}BuilderprivatecreationModeCard(mode:CreationMode){Column(){Text(mode.title).fontSize(18).fontWeight(FontWeight.Bold)Text(mode.desc).fontSize(14).opacity(0.7)Progress({value:mode.progress,type:ProgressType.Linear}).width(100%)}}项目中 Index.ets 定义了约40 个Builder方法这是 ArkTS 推荐的 UI 片段复用方式。Builder可以接受参数生成动态 UI 内容。三、强类型接口与数据模型ArkTS 要求所有数据结构必须明确定义类型不允许隐式 any。项目中大量使用interface来定义数据模型// Index.ets 中的接口定义interfaceArtwork{id:number;title:string;date:string;type:string;color:string;score:number;story:string;}interfaceChatMessage{id:number;role:string;text:string;imageUri:string;}interfaceMetric{name:string;value:number;}interfaceCreationMode{title:string;desc:string;icon:string;color:string;progress:number;}在 ViewModel 层还可以使用Resource类型来引用系统资源这是 ArkTS 特有的一种类型安全方式// CatalogueItemData.etsexportclassCatalogueItemData{id:number0;title:Resource$r(app.string.responsive_layout);uri:string;params?:string;constructor(id:number,title:Resource,uri:string,params?:string){this.idid;this.titletitle;this.uriuri;this.paramsparams;}}与 TypeScript 的区别TypeScript 中使用Resource类型须从模块导入而 ArkTS 中Resource是内置类型配合$r()函数使用——$r(app.string.responsive_layout)会在编译时就检查资源是否存在。四、常量与只读数组ArkTS 中推荐使用const定义常量使用readonly修饰不可变属性。项目中常见的模式// 模块级常量constNAV_ITEMS:string[][首页,创作,我的];constNAV_ICONS:string[][⌂,,♙];constSECONDARY_NONE:number0;constSECONDARY_WORKS:number1;// 数据常量直接在模块作用域定义constWORKS:Artwork[][{id:1,title:蜡笔森林小恐龙,date:2026-05-08,type:幻想生物,color:#AEEBFF,score:92,story:...},{id:5,title:相亲相爱一家人,date:2026-04-16,type:角色伙伴,color:#D8F7EA,score:90,story:...},// ...];constMETRICS:Metric[][{name:想象力,value:85},{name:色彩运用,value:78},{name:构图能力,value:72},{name:细节表达,value:80},{name:创意独特性,value:90}];// 组件内的只读属性privatereadonlypagePadding:number18;privatereadonlybrandPurple:string#7657F3;privatereadonlysoftBackground:string#F7F5FF;说明这些数据常量定义在模块作用域中而不是组件内部属于模块级共享数据可以被组件内的build()方法直接引用不会触发不必要的组件刷新。这是 ArkTS 中常见的性能优化模式。五、泛型与工具类ArkTS 完全支持 TypeScript 的泛型语法。项目中有一个非常经典的泛型应用——BreakPointTypeT// BreakpointSystem.etsdeclareinterfaceBreakPointTypeOptionTextendsRecordstring,T|undefined{sm?:T;md?:T;lg?:T;xl?:T;xxl?:T;}exportclassBreakPointTypeT{options:BreakPointTypeOptionT;constructor(option:BreakPointTypeOptionT){this.optionsoption;}getValue(currentBreakPoint:string):T{returnthis.options[currentBreakPoint]asT;}}在 Index.ets 中这个泛型工具被用于不同响应式断点下的取值// 根据断点返回不同数值privatepageEdge():number{returnnewBreakPointTypenumber({sm:12,md:24,lg:36,xl:56}).getValue(this.currentBreakpoint);}privatepanelWidth():string{returnnewBreakPointTypestring({sm:90%,md:86%,lg:74%,xl:64%}).getValue(this.currentBreakpoint);}privateheroHeight():number{returnnewBreakPointTypenumber({sm:420,md:430,lg:460,xl:480}).getValue(this.currentBreakpoint);}BreakPointTypeT通过泛型参数T实现了类型安全的响应式取值——当断点为md时自动返回中间值断点为xl时返回大屏值。且返回类型与传入类型一致number 返回 numberstring 返回 string无需手动类型转换。六、import 与模块系统ArkTS 使用标准的 ES Module 语法导入模块。项目中展示了三种导入风格// 1. 导入系统 Kit 能力import{common}fromkit.AbilityKit;import{hilog}fromkit.PerformanceAnalysisKit;import{mediaquery}fromkit.ArkUI;import{harmonyShare,systemShare}fromkit.ShareKit;// 2. 导入项目内部模块通过 oh-package.json5 配置的别名import{BreakpointSystem,BreakPointType}fromohos/common;// 3. 导入相对路径模块import{AIGenerationService,GeneratedImage}from../services/AIGenerationService;import{VoiceRecognitionCallbacks,VoiceRecognitionService}from../services/VoiceRecognitionService;HarmonyOS Kit 的导入格式为from kit.ModuleName这是 ArkTS 特有的导入语法。项目内部模块则通过oh-package.json5的ohos/common别名引用。七、类与封装ArkTS 中的类class支持完整的访问修饰符和封装模式。以 Logger 为例// Logger.etsexportclassLogger{privatereadonlyprefix:stringtestTag;privatereadonlydomain:number0xFF00;privatereadonlyformat:string%{public}s, %{public}s;publicdebug(...args:string[]):void{hilog.debug(this.domain,this.prefix,this.format,args);}publicinfo(...args:string[]):void{hilog.info(this.domain,this.prefix,this.format,args);}publicwarn(...args:string[]):void{hilog.warn(this.domain,this.prefix,this.format,args);}publicerror(...args:string[]):void{hilog.error(this.domain,this.prefix,this.format,args);}}再看 Service 层的静态方法类设计// AIGenerationService.ets 中的静态方法类典型的 Service 设计模式exportclassAIGenerationService{staticasyncgenerateImage(prompt:string):PromiseGeneratedImage{/* ... */}staticasyncgenerateVideo(imageUrl:string,prompt:string):PromiseGeneratedVideo{/* ... */}}// PermissionGuard 同样是全静态方法的设计exportclassPermissionGuard{staticasyncrequestCamera():PromisePermissionResult{/* ... */}staticasyncrequestAlbum():PromisePermissionResult{/* ... */}staticasyncrequestMicrophone():PromisePermissionResult{/* ... */}}工程实践项目中 Service 层普遍采用全静态方法类的模式不实例化直接通过AIGenerationService.generateImage()调用。这种模式在 ArkTS 中非常常见适合无状态的服务封装。八、箭头函数与回调ArkTS 支持箭头函数语法项目中大量使用// 简洁的回调表达式privatereadonlyknockShareCallback(target:harmonyShare.SharableTarget):void{this.handleKnockShare(target).catch((error:Error){this.showNotice(碰一碰分享失败this.getErrorMessage(error));});};// 数组遍历与操作privaterefreshWorks():void{this.savedWorksWorkRepository.list().reverse();}九、常见陷阱与注意事项9.1 build() 方法中不能使用流程控制语句ArkTS 的build()方法中不能使用if/else条件语句除三元运算符外和for循环除ForEach/LazyForEach外。如果要条件渲染必须使用三元表达式或Builderbuild(){Column(){// ✅ 正确使用三元表达式this.secondaryPageSECONDARY_WORKS?this.worksPage():this.homePage()// ❌ 错误不能在 build() 中使用 if// if (this.secondaryPage SECONDARY_WORKS) { this.worksPage() }}}9.2 禁止隐式 any// ❌ 错误禁止隐式 any// let data getData();// ✅ 正确必须显式声明类型// let data: Artwork[] getData();// 或// let data getData() as Artwork[];9.3 回调中的 this 捕获在 ArkTS 中箭头函数自动捕获外部的this而普通函数则不会。项目中统一使用箭头函数// ✅ 正确箭头函数自动捕获 thissetInterval((){this.animationFrame(this.animationFrame1)%6;this.generationProgressMath.min(this.generationProgress2,98);},1200);// ❌ 错误的做法普通函数会丢失 this// setInterval(function() {// this.animationFrame; // this 指向错误// }, 1200);十、总结本文通过画伴梦工厂项目的真实代码介绍了 ArkTS 的核心语法特性。从装饰器、强类型接口、泛型工具到模块导入、类封装和箭头函数——ArkTS 在保持 TypeScript 熟悉的语法风格的同时通过编译时强类型检查、声明式 UI 装饰器和严格的语法约束为鸿蒙应用开发提供了更安全、更高效的编码体验。下一篇预告第 1.2 篇《ArkUI 声明式 UI 基础组件、布局与样式》——我们将深入 Index.ets 中数十个Builder构建的 UI 片段学习 Column/Row/Stack 布局、Text/Image/Button 组件、以及鸿蒙特有的$r资源引用体系。参考源码products/default/src/main/ets/pages/Index.ets— 页面组件、状态管理、Builder、响应式布局common/src/main/ets/utils/Logger.ets— 类封装与 hilog 日志common/src/main/ets/utils/BreakpointSystem.ets— 泛型工具类设计products/default/src/main/ets/viewmodel/CatalogueItemData.ets— Resource 类型与数据模型products/default/src/main/ets/components/CreationComponents.ets— Link 与 Component