Hyperapp原始碼分析

Jogis發表於2019-02-28
Hyperapp原始碼分析

前言

Hyperapp是一個輕量級檢視庫,擁有完備的介面渲染、以及檢視資料互動更新能力。專注於檢視渲染的核心部分,使得它的體積非常輕巧,也使得它具備”無限可能”。在設計上並無涉及太多複雜場景,尤為適用於輕量級的移動開發。

特點

1. 外接Action管理

Hyperapp僅關心狀態渲染、排程生成後actions物件。在狀態管理上,我們可以自主使用fluxredux,甚至無需使用任何狀態管理庫。

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在細看一些實現上,會覺得有些”不嚴謹”,可能會被鑽空子。比如:cloneget等函式實現,或者是PromiseArray的判斷。

事實上,這些函式用於在有標準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渲染效能表現不亞於現有主流渲染庫。

Hyperapp原始碼分析

5. SSR支援

Hyperapp雖然精巧,卻完全支援SSR特性。在初次渲染時候,會將現有DOM結構轉成vdom,當有行為觸發資料變動時,高效進行dom-diff以更新現有檢視。

Link

相關文章