最近部門也在跟進鴻蒙平臺的業務開發,自己主要是做 Android 開發,主要使用 Kotlin/Java 語言。,需要對新的開發平臺和開發模式進行學習,在業余時間開了個項目練手,做了個基于 Hexo 博客內容開發的App。鴻蒙主要使用ArkTS語言和ArkUI框架進行開發,有使用 Jetpack Compose 和 JavaScript/TypeScript 的開發經驗的話,上手會比較的輕松。本文主要介紹做的App功能以及對鴻蒙開發體驗的一個總結。
App 簡介
后臺數據來自 Hexo 生成的博客文章,利用 hexo-generator-wxapi 生成 api .json 文件,再利用 七牛云 提供對圖片和 .json 文件 CDN。
實現的功能
- 博客列表分頁加載
- 文章詳情加載
- 文章按分類/標簽展示
- 文章內容統計
- 深色/淺色模式切換
- 數據本地緩存
功能預覽
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
依賴項
Hexo
- Hexo 快速、簡潔且高效的博客框架
- hexo-generator-wxapi 用于將 Hexo 博客內容生成 api 風格的.json文件
- 七牛云 提供對圖片和.json文件 CDN加速
HarmonyOS
- ArkTS ArkTS在TypeScript(簡稱TS)生態基礎上做了進一步擴展,保持了TS的基本風格,同時通過規范定義強化開發期靜態檢查和分析,提升代碼健壯性,并實現更好的程序執行穩定性和性能。
- ArkUI ArkUI(方舟UI框架)為應用的UI開發提供了完整的基礎設施,包括簡潔的UI語法、豐富的UI功能(組件、布局、動畫以及交互事件),以及實時界面預覽工具等,可以支持開發者進行可視化界面開發。
- ohos_pull_to_refresh 列表加載/刷新控件(沒有’No more’的狀態)
- MMKV 是基于 mmap 內存映射的 key-value 組件
鴻蒙開發總結
ArkTs 語言
ArkTS 是 TypeScript 的超集,TypeScript 又是 JavaScript 的超集,所以對于基本數據類型使用的是 TypeScript 語法。他們三者的關系如下圖所示:
相關的差異可以參考社區話題討論 ArkTS與Typescript的區別?
上圖也來自這里的討論。
這里主要記錄一下自己使用過程中踩過的坑:
基本語言類型
Number 和 number 是兩個不同的類型,Number 是 JavaScript 中的一個全局對象,可以使用 new Number() 來創建一個 Number 對象。同理對于 String 和 string,Boolean 和 boolean 也是一樣的,大寫開頭的是包裝對象類型,小寫的是原始類型,這點Java/kotlin也有類似的包裝對象比較好理解,但 Object 居然也有大小寫之區分相比難理解點,寫代碼的時候好幾次忽略了這個事,Object 是所有對象的基類,object 表示非原始類型(即不是 number、string、boolean、symbol、null 或 undefined 的所有類型)。可以是任何對象、數組、函數、類實例等。
let obj: object;
obj = { a: 1 }; // ? 正確:普通對象
obj = [1, 2, 3]; // ? 正確:數組
obj = () => {}; // ? 正確:函數
obj = new Date(); // ? 正確:類實例obj = 42; // ? 錯誤:原始類型 number
obj = "hello"; // ? 錯誤:原始類型 string
兩則的區別
特性 | object | Object |
---|---|---|
允許的值 | 僅非原始類型(對象、數組等) | 任意類型(包括原始值) |
原始值處理 | 禁止 | 自動裝箱(如 42 → Number) |
使用場景 | 明確限制為非原始類型時 | 極少使用(通常用 unknown 或具體類型替代) |
Map 等集合類當作普通 JavaScript 對象來操作
let map = new Map<string, object>();
map["key"] = value; // ? 錯誤用法!
console.log(map.get("biz")); // ? 輸出 undefined
最開始挺奇怪的 map 明明設置了值,但是對應的 map size 為0,遍歷 map 也沒有數據。后來才發現是這種方式 不會 觸發 Map 的內部機制,而是繞過了 Map 的方法,直接操作對象的屬性,賦值后,鍵值對 不會 被存入 Map 的真實存儲中,而是作為對象的普通屬性存在。正確的用法是:
let map = new Map<string, object>();
map.set["key"] = value; // ? 正確用法!
console.log(map.get("biz")); // ? 輸出 value
struct 的困擾
在 js 里面是沒有 struct
這個關鍵詞的,從剛接觸到現在它唯一的作用就是:和 @Component
綁定聲明一個UI控件。例如:
@Component
export struct ToolBar{}
@Component
和 struct
兩則缺一不可,既然必須有 @Component
來標注這是一個UI控件,為什么不能下面這樣呢?能省掉一個關鍵字。
@Component
export class ToolBar {}
同樣困擾的人還有很多,這里有一份討論定義組件時的stuct關鍵字是什么?
官方也有一份聊勝于無的介紹
struct和class的區別是什么?
struct只在自定義組件中使用,@Component裝飾的struct就是自定義組件,自定義組件和class是兩個概念,自定義組件沒有類型,也不能等同于class。如果開發者需要使用組件作為參數在組件之間傳遞,可以使用自定義占位節點。
我猜測這樣是為了省掉對@Component
裝飾器編譯的工作量,如果使用 class 聲明,那么聲明的UI控件就有“面向對象”的能力,實際上只希望它是一個UI控件聲明,不需要它有其他的能力。難道不能對 @Component
裝飾過的對象收回“面向對象”的能力么?當然能啊,估計要做很多編譯檢查的事兒。另外,從開發理解的層面上來講,它確實也已經不是"對象"了,它只是一個干巴巴的一個UI結構,所以干脆就搞了一個新的關鍵詞 struct。
ArkUI 框架
整體框架使用的方式和 Jetpack Compose 類似,都是聲明式UI框架。compose 里面使用 @Composable
來標記某個方法這個方法便成了UI控件
,控件里面的狀態管理使用 remember
+ mutableState
來控制。而 ArkUI 通過 @State、@Link、@Prop 等裝飾器來控制。了解了這些個裝飾器的用法,基本上就能理解 ArkUI 的開發流程了。
構建 UI 的 @Component @Builder
@Component 和 @Builder 組合起來實現的差不多就是 Compose 里面使用 @Composable
裝飾某個方法的作用,用于構建 UI 或可復用的邏輯單元。
@Component
用于創建一個自定義組件,組件可以包含獨立的 UI 結構、狀態管理和生命周期。
@Builder
定義可復用的 UI 片段,用于創建一個UI 構建函數,封裝一段可復用的 UI 代碼塊。不是獨立組件,而是嵌入到其他組件或布局中執行,主要作用是復用和邏輯隔離,例如:關于頁面,里面的文本是差不多的樣式,只是內容不一樣,那么只需要保留一個 text 屬性出來接收參數。或者某塊UI比較復雜,可以抽離一部分UI成為一個獨立的UI邏輯模塊。
構建 UI 的狀態控制裝飾器
@State
比較常用的裝飾器,和 Compose 里面 remember+mutableStateOf 的作用差不多,對應的值改變之后,對相關的使用到該屬性UI的地方進行刷新。
@Prop
@Prop 裝飾的變量和父組件建立單向的同步關系,@Prop變量允許在本地修改,但修改后的變化不會同步回父組件。
也就是在某個 @Component 的組件內有一個 @State 裝飾的屬性,傳遞到子 @Component 組件 @Prop 修飾的屬性。子控件對這個屬性修改之后,父控件不會對這個改變感知,父控件UI不會改變。
@Link
子組件中被@Link裝飾的變量與其父組件中對應的數據源建立雙向數據綁定。
跟 @Prop 的作用類似,不過是雙向的,子控件對這個屬性修改之后,父控件會感知這個變化,父控件UI會隨著這個屬性改變而改變。
@BuilderParam
主要用于動態注入 UI 構建邏輯(即 @Builder 函數),實現父組件向子組件傳遞可定制的 UI 片段,也就是向子控件傳遞 UI 參數。
基本上比較常用到的就這些,還有很多例如:@LocalBuilder @StorageLink @Styles等,都是為了解決開發過過程中遇到的問題,但是只要掌握了 ArkUI UI組件的聲明周期和狀態管理的基本原理理解其他裝飾器還是比較簡單的。
總結
總體開發體驗下來,鴻蒙開發學習成本并不是特別高,比較快能上手,但設計的 api 更像一個縫合怪,且使用上不太收斂。很多庫還需要再建設,例如音視頻開發對應的支持庫還不是特別成熟。不過,作為一個從頭搞的生態來說能實現成這樣已經很不錯了,就像此前武磊登陸西甲,以及目前被看好的青年新星王鈺棟,都是"自己的孩子",需要邁出第一步。現在,很多公司也在適配鴻蒙了,期待未來能從 Android 跟 iOS 的生態中爭奪出一片大市場。
工程相關源碼:
blog_harmony