前言
Hyperapp是一個輕量級檢視庫,擁有完備的介面渲染、以及檢視資料互動更新能力。專注於檢視渲染的核心部分,使得它的體積非常輕巧,也使得它具備”無限可能”。在設計上並無涉及太多複雜場景,尤為適用於輕量級的移動開發。
特點
1. 外接Action管理
Hyperapp
僅關心狀態渲染、排程生成後actions物件。在狀態管理上,我們可以自主使用flux
、redux
,甚至無需使用任何狀態管理庫。
2. 外接渲染模板(語法)
Hyperapp
提供vnode
生成輔助函式,但並不限制渲染模板的選擇,我們可以自由選擇類似JSX
,甚至類VUE
的模板語言。
3. 單向資料流原則
在Hyperapp
初始渲染之後,觸發檢視更新的唯一方式是,通過呼叫action
變更狀態,從而觸發檢視更新。這使得我們可以建立易於跟蹤、健壯、可維性強的應用。
大話Hyperapp原始碼
詳細的分析,可以在原始碼註釋倉庫下看到,裡面有hyperapp
各個原始碼重要細節的分析。下面來介紹一下hyperapp
原始碼有意思的地方:
1. 麻雀雖小,五臟俱全
專注於檢視渲染&資料互動更新,在實現上也是恰到好處地實現這些功能。具備內建狀態驅動的檢視更新引擎、標準VNode
四板斧、DOM-diff
機制。在這點來說,hyperapp
處於新生期,需要具備完善的生態,才可以發揮出強大的核心能力。
VNode四板斧:
// 基本的HTML標籤都可以被抽象成如下形式:
// {
// nodeName,
// attributes,
// children,
// key
// }
// TextNode只有一個nodeValue,SVG也是比較特殊,所以在更新時候也會對這兩種型別做特殊處理
複製程式碼
DOM-diff 原則:
// 1. 平級對比,非平級則認為是不一樣的dom,直接剷平重建
// 2. 只更新同型別節點,非同型別一樣剷平重建
// 3. 儘可能利用現有dom,免除額外的刪除建立開銷,只需要重新插入(appendChild or insertBefore)
// 4. index&key相同的vdom,對應的dom無需對比,直接複用,下一個!
複製程式碼
2. 剛剛好,就是最好的
hyperapp
在細看一些實現上,會覺得有些”不嚴謹”,可能會被鑽空子。比如:clone、get等函式實現,或者是Promise、Array的判斷。
事實上,這些函式用於在有標準DOM結構的實現、自呼叫的原始碼上,作為判斷能達到”剛剛好”的要求。既不會浪費效能體積,也不會導致出錯。
function get(path, source) {
for (var i = 0; i < path.length; i++) {
source = source[path[i]]
}
return source
}
// const result = { winner: { name: `Tony` } }
// get([`winner`, `name`], result) => Tony
複製程式碼
不必具備lodash get
的相容性,以最優形態抽象出適用於原始碼的函式,便是最好的。
3. 簡單的生命週期
說出來你可能不信,hyperapp
僅有四個生命週期函式。
他們分別是:
- 檢視渲染
- 初始渲染後:
oncreate(DOMElement)
- 檢視更新後:
onupdate(DOMElement)
- 初始渲染後:
- 檢視銷燬
- 銷燬前執行:
onremove(DOMElement, action)
- 可以控制非同步銷燬,需要手動呼叫action函式才會移除DOMElement
- 銷燬前通知:
ondestory(DOMElement)
- 不能控制自己被銷燬,可以在銷燬前做一些同步操作,比如釋放第三方庫,防止記憶體洩露
- 銷燬前執行:
這使得hyperapp
比較適用於輕互動場景,配合webpack
的模板語法編譯能力,可以實現非常輕量級的移動應用。
4. 嚴格的key控制
在列表渲染時候,hyperapp
嚴格要求元件提供對應key
屬性。
如果沒有對應的key
,相當於預設每次渲染都是全新的列表,這會涉及到原有列表DOM
的銷燬、新列表DOM
建立以及新增,大型列表上有可能會導致效能問題。
也正因為這個特性,使得在良好結構下,hyperapp
的渲染效能表現不亞於現有主流渲染庫。
5. SSR支援
Hyperapp
雖然精巧,卻完全支援SSR
特性。在初次渲染時候,會將現有DOM
結構轉成vdom
,當有行為觸發資料變動時,高效進行dom-diff
以更新現有檢視。
Link
- Hyperapp倉庫:github.com/hyperapp/hy…
- 原始碼註釋倉庫:github.com/yesvods/hyp…
- 舊版本渲染效能報告:rawgit.com/krausest/js…
- 渲染效能Runner:mathieuancelin.github.io/js-repaint-…
- PerformanceIssue:github.com/hyperapp/hy…