相關學習推薦:javascript影片教學
#眾所周知,剛剛開源的「鴻蒙2.0」以JavaScript 作為IoT應用開發的框架語言。這標誌著繼 SpaceX 上天之後,JavaScript 再一次蹭到了新聞聯播級的熱點。這麼好的機會,只拿來陰陽怪氣實在太可惜了。身為科普,這篇文章不會拿著放大鏡找出程式碼中的槽點來吹毛求疵,而是希望通俗地講清楚它所支援的 GUI 到底是怎麼一回事。只要對計算機基礎有個大概的了解,應該就不會對本文有閱讀上的障礙。
我們已經知道在「鴻蒙 2.0」上,開發者只需編寫形如 Vue 元件式的 JavaScript 業務邏輯,即可將其渲染為智慧手錶等嵌入式硬體上的 UI 介面。這個過程中需要涉及哪些核心的模組呢?這些模組中又有哪些屬於自研,哪些使用了現成的開源專案呢?這裡將其分為自上而下的三個抽象層來介紹:
- JS 框架層,可理解為一個大幅簡化的Vue 式JavaScript 框架
- JS 引擎與運行時層,可理解為一個大幅簡化的WebKit 式運行時
- 圖形渲染層,可理解為一個大幅簡化的Skia 式圖形繪圖函式庫
這三個抽象層,整體構成了一套針對嵌入式硬體的GUI 技術堆疊。有別於許多高喊「不明覺厲/ 深不可測」的輿論,個人認為至少對於GUI 部分,國內凡是接觸過目前主流Hybrid 式跨端方案或JS 運行時研發的一線開發者,都很容易從源碼出發來理解它。下面逐層對其做一些解讀和分析。
JS 框架層
從最頂層的視角出發,要想用「鴻蒙2.0」渲染出一段動態的文本,你只需要寫如下的HML(類XML)格式程式碼:
<!-- hello.hml --><text>{{hello}}</text>复制代码
然後在同級目錄寫這樣的JavaScript:
// hello.jsexport default { data: { hello: 'PPT' }, boil() { this.hello = '核武器'; } }复制代码
這樣只要點擊文本,就會呼叫boil
方法,讓PPT
變成核武
。
這背後發生了什麼事?熟悉 Vue 2.0 的同學應該會立刻聯想到下面這幾件事:
- 需要對 XML 的預處理機制,將其轉換為 JS 中的巢狀函數結構。這樣只要在執行時做一次簡單 eval ,即可用 JS 產生符合 XML 結構的 UI。
- 需要事件機制,使得觸發
onclick
事件時能執行對應回呼。 - 需要資料劫持機制,使得對
this.hello
賦值時能執行對應回呼。 - 需要能在回呼中更新 UI 物件控制項。
這幾件事分別是怎麼實現的呢?簡單說來是這樣的:
-
XML 預處理依賴現成的NPM 開源包,從而把XML 中的
onclick
屬性轉換為JS 物件的屬性字段。 -
事件的註冊和觸發都直接由 C 實作。如上一步所獲得的 JS 物件
onclick
屬性會在 C 中被檢查和註冊,相當於全部元件均為原生。 -
資料劫持機制用 JS 實現,是基於
Object.defineProperty
的(幾百行量級的)ViewModel。 -
UI 控制項的更新,會在 ViewModel 自動執行的 JS 回呼中,呼叫 C 的原生方法實作。這部分完全隱式完成,並未開放
document.createElement
式的標準化 API。
由於大量常見JS 框架中的能力都直接做進了C ,所以整套GUI 技術堆疊裡用純JavaScript 所實現的東西(主要見ace_lite_jsfwk
倉庫下的core/index.js
、observer.js
和subject.js
),相當於有且只有這麼一個功能:
一個可以watch 的ViewModel。
至於純 JS 框架部分的實現複雜度和質量,客觀地說如果是個人業餘作品,可以當作校招面試中不錯的加分項。
JS 引擎與運行時層
理解了JS 框架層之後,我們既可以認為“鴻蒙2.0”選擇把高度簡化後的Vue 深度定制進了C 裡,也可以認為它緊密圍繞著高度簡化(且私有)的DOM 實現了配套的前端框架。因此要繼續探索這套 GUI 的原理,我們必須進入其 C 部分,了解其 JS 引擎與運行時層的實現。
JS 引擎和運行時之間,有什麼區別與連結呢? JS 引擎一般只需符合 ECMA-262 規範,其中沒有任何帶有「副作用」的平台 API 的定義。從setTimeout
到document.getElementById
到console.log
再到fs.readFile
,這些能執行實際IO 操作的功能,都需要由「將引擎API 和平台API 膠合到一起」的運行時提供。運行時本身的原理並不複雜,譬如在個人的文章《從 JS 引擎到 JS 運行時》中,你就可以看到如何借助現成的 QuickJS 引擎,自己搭建一個運行時。
那麼在「鴻蒙 2.0」中,JS 運行時是如何搭建出來的呢?有這麼幾個重點:
- JS 引擎選擇了 JerryScript,這是一款由三星開發的嵌入式 JS 引擎。
- 每種形如
<text></text>
和<p></p>
的XML 標籤元件,都對應一個綁定到JerryScript 上的C Component 類,如TextComponent
和pComponent
等。 - 除UI 原生物件外,還有一系列在JS 中以
@system
為前綴的built-in 模組,它們提供了JS 中可用的Router / Audio / File 等平台能力(參見ohos_module_config.h
)。
這裡特別值得一提的是 Router。它和vue-router 等常見Web 平台路由的實作原理有很大區別,是專門在運行時內深度定制的(參見router_module.cpp
、js_router.cpp
和js_page_state_machine.cpp
)。簡單說來這個「路由」是這樣實現的:
- 在 JS 中呼叫切換頁面的
router.replace
原生方法,走進 C 。 - C 中根據新頁面 URI 路徑(如
pages/detail
)載入新頁面 JS,新頁面狀態機實例,將其切換至 Init 狀態。 - 在新狀態機的 Init 過程中,呼叫 JS 引擎到 eval 新頁面的 JS 程式碼,取得新頁面的 ViewModel。
- 將路由參數附加到 ViewModel 上,銷毀舊狀態機及其上的 JS 物件。
所以我們可以發現,這裡所謂的「切換路由」,其實更接近 Web 瀏覽器的「刷新頁面」。那我們可以認為這個 JS 運行時的能力,已經可以對標 WebKit 等級的瀏覽器核心了嗎?
當然還差得很遠。與WebKit 相比,它並未支援對HTML 和CSS 的解析(二者都會在開發階段被解析轉換成同等執行效果的JS),也沒有瀏覽器中持續動態載入、解析與執行資源的挑戰(小程式不外乎是幾個本地的靜態JS 檔案)。至於排版佈局和渲染方面自然也有很大差距,這點會在最後一節提及。
另外,相信很多同學都會對 JerryScript 引擎感到好奇。本部分最後分享一些個人對此所掌握的消息。
JerryScript 引擎是一款專為嵌入式硬體實現的 JS 解譯器,只支援到 ES5.1 標準。在QuickJS Benchmark 中,可以查看到它們的效能比較結果:

可以看到論效能,JerryScript 在無JIT 的引擎中大幅弱於QuickJS 和Hermes。如果和開啟了 JIT 的 V8 相比,甚至會慢出兩個數量級。因此這是非常特定於低階設備的引擎,如果需要支援 React 和 Vue 這類中大型前端專案中標配的基礎庫(甚至是其對應全家桶),仍然可能需要使用更強大的引擎。
對於JerryScript 的使用,有同場景重度應用經驗的當屬RT-Thread 創始人@午夜熊,他們和某國內一線廠商合作研發的智能手錶就用JerryScript 實現了UI,目前產品馬上就要上市了。他們團隊對 JerryScript 的一些使用回饋也吻合上述評價,概括說來是這樣的:
- JerryScript 在体积和内存占用上,相比 QuickJS 有更好的表现。
- JerryScript 的稳定性弱于 QuickJS,有一些难以绕过的问题。
- JerryScript 面对稍大(1M 以上)的 JS 代码库,就有些力不从心了。
那么师出名门的 QuickJS 和 Facebook 的 Hermes,是否就是无 JIT 式 JS 引擎的下一代标杆了吗?倒也未必如此。这方面可以参考个人的知乎回答:随着 TypeScript 继续普及,会不会出现直接跑 TypeScript 的运行时?这里提到的微软为教育项目 MakeCode 研发的 Static TypeScript,就相当有潜力成为下一代的高性能 JS 系语言环境。通过限定 TypeScript 的静态强类型子集并为其搭建工具链,STS 可以做到无需 JIT 也能接近 V8 的性能水平,同时内存占用比 V8 少两个数量级。这使得 STS 不光能用于开发普通 app 这类 IO 密集的应用,还能顺利在嵌入式硬件上开发小游戏这类更偏计算密集(需逐帧更新渲染)的应用,在工程能力上是一项很大的突破。
所以说,当「鸿蒙 2.0」还需要熟练开发者勉强搭建出环境跑通 Hello World 时,微软已经让上百万小朋友都能用 TypeScript 在网页里给教学用的掌上游戏机写小游戏入门编程了。这里没什么唱反调的意思,只希望提醒一下我们在为国产「里程碑」欢呼时,也要清醒地看到业界前沿的动向,仅此而已。
图形绘制层
理解 JS 运行时之后,还剩最后一个问题,即 JS 运行时中的各种 Component 对象,是如何被绘制为手表等设备上的像素的呢?
这就涉及「鸿蒙 2.0」中的另一个 graphic_lite
仓库了。可以认为,这里才是真正执行实际绘制的 GUI。像之前的 TextComponent
等原生组件,都会对应到这里的某种图形库 View。它以一种相当经典的方式,在 C++ 层实现并提供了「Canvas 风格的立即模式 GUI」和「DOM 风格的保留模式 GUI」两套 API 体系(对于立即模式和保留模式 GUI 的区别与联系,可参见个人这篇 IMGUI 科普回答)。概括说来,这个图形子系统的要点大致如下:
- 图形库提供了
UIView
这个 C++ 控件基类,其中有一系列形如OnClick
/OnLongPress
/OnDrag
的虚函数。基本每种 JS 中可用的原生 Component 类,都对应于一种 UIView 的子类。 - 除了各种定制化 View 之外,它还开放了一系列形如
DrawLine
/DrawCurve
/DrawText
等命令式的绘制方法。 - 这个图形库具备名为 GFX 的 GPU 加速模块,但它目前似乎只有象征性的
FillArea
矩形单色填充能力。
在基础 UI 控件方面,不难找到一些值得一提的自研模块特性:
- 支持了简易的 RecycleView 长列表。
- 支持了简易的 Flex 布局。
- 支持了内部的 Invalidate 脏标记更新机制。
至于 2D UI 渲染中的几项关键能力,则基本可分为路径、位图和文字三类。这个图形库在这几个方面都有涉及,最后简单介绍一下。
首先对于位图,这个图形库依赖了 libpng
和 libjpeg
做图像解码,然后即可使用内存中的 bitmap 图像做绘制。
然后对于路径,这个图形库自己实现了各种 CPU 中的像素绘制方法,典型的例子就是这个贝塞尔曲线的绘制源码:
void DrawCurve::DrawCubicBezier(const Point& start, const Point& control1, const Point& control2, const Point& end, const Rect& mask, int16_t width, const ColorType& color, OpacityType opacity) { if (width == 0 || opacity == OPA_TRANSPARENT) { return; } Point prePoint = start; for (int16_t t = 1; t <p>基于高中的数学知识,我们不难明白这种曲线是如何绘制出来的:取足够多的点(也就是那个默认 1000 的 <code>INTERPOLATION_RANGE</code>)作为插值输入,逐点计算出曲线表达式的 XY 坐标,然后直接修改像素位置所在的 framebuffer 内存即可。这种教科书式的实现是最经典的,不过如果要拿它对标 Skia 里的黑魔法,还是不要勉为其难了吧。</p><p>最后对于文字的绘制,会涉及一些字体解析、定位、RTL和折行等方面的处理。这部分实际上也是组合使用了一些业界通用的开源基础库来实现的。比如对于「牢」这个字,就可以找到图形库的这么几个开源依赖,它们各自扮演不同的角色:</p>
-
harfbuzz
- 用来告诉调用者,应该把「牢」的 glyph 字形放在哪里。 -
freetype
- 从宋体、黑体等字体文件中解码出「牢」的 glyph 字形,将其光栅化为像素。 -
icu
- 处理 Unicode 中许多奇葩的特殊情况,这块个人不了解,略过。
到这里,我们就可以理出一个非常概括性的渲染流程了:
- JS 中執行
this.hello = 'PPT'
之類的程式碼,觸發依賴追蹤。 - JS 依賴追蹤回呼觸發原生函數,更新 C 的 Component 元件狀態。
- Component 更新其綁定的 UIView 子類別狀態,觸發圖形庫更新。
- 圖形庫更新記憶體中的像素狀態,完成繪製。
這就是個人對「鴻蒙 2.0」這套 GUI 技術堆疊的解讀了。時間有限並未進一步深挖,歡迎(文明的)批評指正。
總結
特別聲明:本部分主觀評論僅針對「鴻蒙 2.0」目前的 GUI 框架部分,請勿隨意曲解。
對於「鴻蒙 2.0」在 GUI 部分的亮點,個人能想到這些:
- 確實有務實(但和當年 PPT 介紹完全兩碼事)的程式碼。
- 不是 WebView 套殼,佈局和繪製是自己做的。
- 無需超過大學本科程度的電腦知識,也能順利閱讀理解。
而至於明顯(不只是某幾行程式碼寫得醜)的缺失或問題,目前看來則有這麼一些:
- JS 框架層
- 沒有基本的元件間通訊(如props / emit 等)能力
- 沒有基本的自訂元件能力
- 沒有除基礎依賴追蹤以外的狀態管理能力
- JS 引擎與執行時間層
- 標準支援過低,無法運作Vue 3.0 這類需Proxy 的下一代前端框架
- 效能水準弱,難以支援中大型JS 應用
- #沒有開放DOM 式的物件模型API,不利於上層抹平差異
- #圖形渲染層
- 沒有實質可用的GPU 加速
- 沒有SVG 和富文本等高階渲染能力
- Canvas 完成度低,缺狀態堆疊和很多API
看起來槽點很多,但是你會指責汽車沒有噴射引擎嗎?對於不同複雜度的場景,自然存在著不同的最優架構設計。目前看來,這套設計確實很適合嵌入式硬體和簡易「小程式」的場景。但如果按照所謂「分散式全場景跨平台」的要求來審視,那麼不管比起現代的 Web 瀏覽器還是 iOS 和安卓的 GUI,這套架構的複雜度都是完全無法相提並論的。 如果想在手機上實裝,幾乎必定還需要追加大量複雜模組,進行大幅的架構演化與重新設計。
當然,汽車廠商也不會說自己造的是飛機,對吧?
總之這確實是一盤自己做的麻婆豆腐,但不是某些人口中的滿漢全席。
最後是個人的主觀評論:
首先,這套 GUI 技術堆疊達到了組裝和借鏡開源產品時所能獲得的主流水平。但論性能與表現力上限,其核心模組距離微軟 MakeCode 這類業界 cutting-edge 級的產學研結合前緣方案,仍有數量級的世代差距。
其次,不必把它當作需要海量專家精密計算的Rocket Science——不是貶低自主研發,而是真心地希望大家能明白,「這件事我也可以實際參與進來!」作業系統和GUI 沒有那麼神秘,已有很多國產的成熟開源產品可供學習、使用與貢獻(這裡順便推薦極易體驗且同為國產的RT-Thread 作為嚐鮮入門之用)。畢竟只有真正搞懂了某個產品在技術上到底是怎麼一回事,才不容易被別有用心的人帶節奏,對吧?
最後,對於所有熟悉 JavaScript 的前端開發者們,你們為什麼還要陰陽怪氣地嘲笑鴻蒙?鴻蒙就是 JavaScript 在中國的財富密碼啊! JavaScript 被鴻蒙這樣的「國之重器」採用,可以大大增強前端的道路自信、理論自信、文化自信和技術堆疊自信。只要以這種形式結合拼接與自研,就可以一舉在全國上下獲得崇高的聲望,這條路真是太讓人心馳神往了呀(小聲)
我們要團結起來,大力弘揚和宣傳JavaScript 在大國競爭中的核威懾級地位,爭取上升到只要說自己會寫JavaScript,大家就會對你肅然起敬的高度——只要你是前端程式設計師,買票可以插隊,搭車可以讓座,開房可以白嫖……好時代,來臨了!
想成為國之棟樑嗎?來寫 JavaScript 吧!
不多說了,我要去實幹興邦啦!
#想了解更多程式設計學習,請關注php培訓欄位!
以上是一起看 鴻蒙 JavaScript GUI 技術棧的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。