<p>相關學習推薦:javascript影片教學<p>#眾所周知,剛剛開源的「鴻蒙2.0」以JavaScript 作為IoT應用開發的框架語言。這標誌著繼 SpaceX 上天之後,JavaScript 再一次蹭到了新聞聯播級的熱點。這麼好的機會,只拿來陰陽怪氣實在太可惜了。身為科普,這篇文章不會拿著放大鏡找出程式碼中的槽點來吹毛求疵,而是希望通俗地講清楚它所支援的 GUI 到底是怎麼一回事。只要對計算機基礎有個大概的了解,應該就不會對本文有閱讀上的障礙。 <p>我們已經知道在「鴻蒙 2.0」上,開發者只需編寫形如 Vue 元件式的 JavaScript 業務邏輯,即可將其渲染為智慧手錶等嵌入式硬體上的 UI 介面。這個過程中需要涉及哪些核心的模組呢?這些模組中又有哪些屬於自研,哪些使用了現成的開源專案呢?這裡將其分為自上而下的三個抽象層來介紹:
<!-- hello.hml --><text onclick="boil">{{hello}}</text>复制代码
// hello.jsexport default { data: { hello: 'PPT' }, boil() { this.hello = '核武器'; } }复制代码
boil
方法,讓PPT
變成核武
。
<p>這背後發生了什麼事?熟悉 Vue 2.0 的同學應該會立刻聯想到下面這幾件事:
onclick
事件時能執行對應回呼。 this.hello
賦值時能執行對應回呼。 onclick
屬性轉換為JS 物件的屬性字段。 onclick
屬性會在 C 中被檢查和註冊,相當於全部元件均為原生。 Object.defineProperty
的(幾百行量級的)ViewModel。 document.createElement
式的標準化 API。 ace_lite_jsfwk
倉庫下的core/index.js
、observer.js
和subject.js
),相當於有且只有這麼一個功能:
<p>一個可以watch 的ViewModel。
<p>至於純 JS 框架部分的實現複雜度和質量,客觀地說如果是個人業餘作品,可以當作校招面試中不錯的加分項。
setTimeout
到document.getElementById
到console.log
再到fs.readFile
,這些能執行實際IO 操作的功能,都需要由「將引擎API 和平台API 膠合到一起」的運行時提供。運行時本身的原理並不複雜,譬如在個人的文章《從 JS 引擎到 JS 運行時》中,你就可以看到如何借助現成的 QuickJS 引擎,自己搭建一個運行時。
<p>那麼在「鴻蒙 2.0」中,JS 運行時是如何搭建出來的呢?有這麼幾個重點:
<text>
和<p>
的XML 標籤元件,都對應一個綁定到JerryScript 上的C Component 類,如TextComponent
和pComponent
等。 @system
為前綴的built-in 模組,它們提供了JS 中可用的Router / Audio / File 等平台能力(參見ohos_module_config.h
)。 router_module.cpp
、js_router.cpp
和js_page_state_machine.cpp
)。簡單說來這個「路由」是這樣實現的:
router.replace
原生方法,走進 C 。 pages/detail
)載入新頁面 JS,新頁面狀態機實例,將其切換至 Init 狀態。 graphic_lite
仓库了。可以认为,这里才是真正执行实际绘制的 GUI。像之前的 TextComponent
等原生组件,都会对应到这里的某种图形库 View。它以一种相当经典的方式,在 C++ 层实现并提供了「Canvas 风格的立即模式 GUI」和「DOM 风格的保留模式 GUI」两套 API 体系(对于立即模式和保留模式 GUI 的区别与联系,可参见个人这篇 IMGUI 科普回答)。概括说来,这个图形子系统的要点大致如下:
UIView
这个 C++ 控件基类,其中有一系列形如 OnClick
/ OnLongPress
/ OnDrag
的虚函数。基本每种 JS 中可用的原生 Component 类,都对应于一种 UIView 的子类。DrawLine
/ DrawCurve
/ DrawText
等命令式的绘制方法。FillArea
矩形单色填充能力。libpng
和 libjpeg
做图像解码,然后即可使用内存中的 bitmap 图像做绘制。
<p>然后对于路径,这个图形库自己实现了各种 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 <= INTERPOLATION_RANGE; t++) { Point point; point.x = Interpolation::GetBezierInterpolation(t, start.x, control1.x, control2.x, end.x); point.y = Interpolation::GetBezierInterpolation(t, start.y, control1.y, control2.y, end.y); if (prePoint.x == point.x && prePoint.y == point.y) { continue; } DrawLine::Draw(prePoint, point, mask, width, color, opacity); prePoint = point; } }复制代码
INTERPOLATION_RANGE
)作为插值输入,逐点计算出曲线表达式的 XY 坐标,然后直接修改像素位置所在的 framebuffer 内存即可。这种教科书式的实现是最经典的,不过如果要拿它对标 Skia 里的黑魔法,还是不要勉为其难了吧。
<p>最后对于文字的绘制,会涉及一些字体解析、定位、RTL和折行等方面的处理。这部分实际上也是组合使用了一些业界通用的开源基础库来实现的。比如对于「牢」这个字,就可以找到图形库的这么几个开源依赖,它们各自扮演不同的角色:
harfbuzz
- 用来告诉调用者,应该把「牢」的 glyph 字形放在哪里。freetype
- 从宋体、黑体等字体文件中解码出「牢」的 glyph 字形,将其光栅化为像素。icu
- 处理 Unicode 中许多奇葩的特殊情况,这块个人不了解,略过。this.hello = 'PPT'
之類的程式碼,觸發依賴追蹤。 <p>特別聲明:本部分主觀評論僅針對「鴻蒙 2.0」目前的 GUI 框架部分,請勿隨意曲解。<p>對於「鴻蒙 2.0」在 GUI 部分的亮點,個人能想到這些:
<p>當然,汽車廠商也不會說自己造的是飛機,對吧?<p>總之這確實是一盤自己做的麻婆豆腐,但不是某些人口中的滿漢全席。 <p>最後是個人的主觀評論: <p>首先,這套 GUI 技術堆疊達到了組裝和借鏡開源產品時所能獲得的主流水平。但論性能與表現力上限,其核心模組距離微軟 MakeCode 這類業界 cutting-edge 級的產學研結合前緣方案,仍有數量級的世代差距。 <p>其次,不必把它當作需要海量專家精密計算的Rocket Science——不是貶低自主研發,而是真心地希望大家能明白,「這件事我也可以實際參與進來!」作業系統和GUI 沒有那麼神秘,已有很多國產的成熟開源產品可供學習、使用與貢獻(這裡順便推薦極易體驗且同為國產的RT-Thread 作為嚐鮮入門之用)。畢竟只有真正搞懂了某個產品在技術上到底是怎麼一回事,才不容易被別有用心的人帶節奏,對吧? <p>最後,對於所有熟悉 JavaScript 的前端開發者們,你們為什麼還要陰陽怪氣地嘲笑鴻蒙?鴻蒙就是 JavaScript 在中國的財富密碼啊! JavaScript 被鴻蒙這樣的「國之重器」採用,可以大大增強前端的道路自信、理論自信、文化自信和技術堆疊自信。只要以這種形式結合拼接與自研,就可以一舉在全國上下獲得崇高的聲望,這條路真是太讓人心馳神往了呀(小聲) <p>我們要團結起來,大力弘揚和宣傳JavaScript 在大國競爭中的核威懾級地位,爭取上升到只要說自己會寫JavaScript,大家就會對你肅然起敬的高度——只要你是前端程式設計師,買票可以插隊,搭車可以讓座,開房可以白嫖……好時代,來臨了! <p>想成為國之棟樑嗎?來寫 JavaScript 吧! <p>不多說了,我要去實幹興邦啦!
<p>想了解更多程式設計學習,請關注php培訓欄位!#
以上是一起看 鴻蒙 JavaScript GUI 技術棧的詳細內容。更多資訊請關注PHP中文網其他相關文章!