小程序的視圖是在WebView里渲染的,那搭建視圖的方式自然就需要用到HTML語言。如果我們直接提供HTML的能力,那前面章節所介紹的為解決管控與安全而建立的雙線程模型就成為擺設了。開發者可以利用A標簽實現跳轉到其它在線網頁,也可以動態執行JavaScript等。
因此,小程序設計了一套組件框架——`Exparser`。基于這個框架,內置了一套組件,以涵蓋小程序的基礎功能,便于開發者快速搭建出任何界面。同時也提供了自定義組件的能力,開發者可以自行擴展更多的組件,以實現代碼復用。
[TOC]
### 5.2.1 Exparser框架
`Exparser`是微信小程序的組件組織框架,內置在小程序基礎庫中,為小程序的各種組件提供基礎的支持。小程序內的所有組件,包括內置組件和自定義組件,都由Exparser組織管理。
Exparser的組件模型與WebComponents標準中的ShadowDOM高度相似。Exparser會維護整個頁面的節點樹相關信息,包括節點的屬性、事件綁定等,相當于一個簡化版的Shadow DOM實現。Exparser的主要特點包括以下幾點:
1. 基于Shadow DOM模型:模型上與WebComponents的ShadowDOM高度相似,但不依賴瀏覽器的原生支持,也沒有其他依賴庫;實現時,還針對性地增加了其他API以支持小程序組件編程。
2. 可在純JS環境中運行:這意味著邏輯層也具有一定的組件樹組織能力。
3. 高效輕量:性能表現好,在組件實例極多的環境下表現尤其優異,同時代碼尺寸也較小。
>[info] 小程序中,所有節點樹相關的操作都依賴于Exparser,包括WXML到頁面最終節點樹的構建、createSelectorQuery調用和自定義組件特性等。
### 5.2.2 內置組件
基于Exparser框架,小程序內置了一套組件,提供了視圖容器類、表單類、導航類、媒體類、開放類等幾十種組件。有了這么豐富的組件,再配合WXSS,我們可以搭建出任何效果的界面。在功能層面上,也滿足絕大部分需求。
一般而言,我們會把一個組件內置到小程序框架里的一個重要原則是:這個組件是基礎的。換句話說,沒有這個組件的話,在小程序架構里無法實現或者實現不好某類功能。
比如像一些開放類組件,有open-data組件提供展示群名稱、用戶信息等微信體系下的隱私信息,有button組件里open-type屬性所提供分享、跳轉App等敏感操作的能力。
還有比如像視圖容器類組件movable-view這種因雙線程模型導致手勢識別不好實現的組件,這是因為手勢識別需要高頻率捕捉手指的觸摸事件,而在雙線程模型中,觸摸事件從渲染層發出,派發到邏輯層,這中間是有一定的延時而導致視圖跟隨手指運動這類交互變得有些卡頓。
### 5.2.3 自定義組件
自定義組件是開發者可以自行擴充的組件。開發者可以將常用的節點樹結構提取成自定義組件,實現代碼復用。
1. ShadowTree的概念
代碼清單6-2 頁面節點樹(`Composed Tree`)
~~~
<view>
<input-with-label>
<label>
TEXT
</label>
<input />
</input-with-label>
</view>
~~~
這里如果將input-with-label抽象成一個組件,那么可以將整個節點樹拆分成兩部分。
代碼清單6-3 組件節點樹(`Shadow Tree`)
~~~
<label><slot/></label>
<input />
~~~
代碼清單6-4 調用組件的節點樹
~~~
<view>
<input-with-label>
TEXT
</input-with-label>
</view>
~~~
在Exparser的組件模型中,組件的節點樹稱為“ShadowTree”,即組件內部的實現;最終拼接成的頁面節點樹被稱為“Composed Tree”,即將頁面所有組件節點樹合成之后的樹。在進行了這樣的組件分離之后,整個頁面節點樹實質上被拆分成了若干個ShadowTree(頁面的body實質上也是一個組件,因而也是一個ShadowTree)。
這樣,各個組件也將具有各自獨立的邏輯空間。每個組件都分別擁有自己的獨立的數據、setData調用,createSelectorQuery也將運行在Shadow Tree的層面上。關于具體如何使用自定義組件特性,這里不再詳細討論,請參閱小程序開發文檔。
2. 運行原理
小程序頁面中,Exparser將接管所有的自定義組件注冊與實例化。
從外部接口上看,小程序基礎庫提供有Page和Component兩個構造器。
以Component為例,在小程序啟動時,構造器會將開發者設置的properties、data、methods等定義段,寫入Exparser的組件注冊表中。這個組件在被其它組件引用時,就可以根據這些注冊信息來創建自定義組件的實例。
Page構造器的大體運行流程與之相仿,只是參數形式不一樣。這樣每個頁面就有一個與之對應的組件,稱為“頁面根組件”。
在初始化頁面時,Exparser會創建出頁面根組件的一個實例,用到的其他組件也會響應創建組件實例(這是一個遞歸的過程)。組件創建的過程大致有以下幾個要點:
* 根據組件注冊信息,從組件原型上創建出組件節點的JS對象,即組件的this;
* 將組件注冊信息中的data 復制一份,作為組件數據,即this.data;
* 將這份數據結合組件WXML,據此創建出Shadow Tree,由于Shadow Tree中可能引用有其他組件,因而這會遞歸觸發其他組件創建過程;
* 將ShadowTree拼接到Composed Tree上,并生成一些緩存數據用于優化組件更新性能;
* 觸發組件的created生命周期函數;
* 如果不是頁面根組件,需要根據組件節點上的屬性定義,來設置組件的屬性值;
* 當組件實例被展示在頁面上時,觸發組件的attached 生命周期函數,如果Shadw Tree中有其他組件,也逐個觸發它們的生命周期函數。
3. 組件間通信
不同組件實例間的通信有WXML屬性值傳遞、事件系統、selectComponent和relations等方式。
WXML屬性值傳遞是從父組件向子組件的基本通信方式,而事件系統是從子組件向父組件的基本通信方式。
Exparser的事件系統完全模仿Shadow DOM的事件系統。在通常的理解中,事件可以分為冒泡事件和非冒泡事件,但在ShadowDOM體系中,冒泡事件還可以劃分為在Shadow Tree上冒泡的事件和在Composed Tree上冒泡的事件。如果在Shadow Tree上冒泡,則冒泡只會經過這個組件Shadow Tree上的節點,這樣可以有效控制事件冒泡經過的范圍。
代碼清單6-5 input-with-label的WXML
~~~
<label>
<input />
<slot />
</label>
~~~
代碼清單6-6 頁面WXML
~~~
<view>
<input-with-label>
<button />
</input-with-label>
</view>
~~~
用上面的例子來說,當在 button 上觸發一個事件時:
* 如果事件是非冒泡的,那只能在 button 上監聽到事件;比如:`click`事件??
* 如果事件是在 Shadow Tree 上冒泡的,那 button 、 input-with-label 、view 可以依次監聽到事件;
* 如果事件是在 Composed Tree 上冒泡的,那 button 、 slot 、label 、 input-with-label 、 view 可以依次監聽到事件。
在自定義組件中使用`triggerEvent`觸發事件時,可以指定事件的`bubbles`、`composed`和`capturePhase`屬性,用于標注事件的冒泡性質。
代碼清單6-7 triggerEvent事例
~~~
Component({
methods: {
helloEvent: function() {
this.triggerEvent('hello', {}, {
bubbles: true, // 這是一個冒泡事件
composed: true, // 這個事件在Composed Tree 上冒泡
capturePhase: false // 這個事件沒有捕獲階段
})
}
}
})
~~~
小程序基礎庫自身也會通過這套事件系統提供一些用戶事件,如`tap`、`touchstart`和form組件的`submit`等。其中,tap等用戶觸摸引發的事件是在ComposedTree上的冒泡事件,其他事件大多是非冒泡事件。
- 微信
- 小程序
- 1. 代碼組成
- 1.1 JSON配置--'*.json'文件
- 1.2 WXML模板--'*.wxml'文件
- 1.3 WXSS樣式--'*.wxss'文件
- 1.4 JavaScript腳本--'*.js'文件
- 2. 客戶端運行
- 2.1 邏輯層和渲染層
- 2.1.1 邏輯層--App Service
- 2.1.2 渲染層/視圖層--View
- 2.1.3 通信模型
- 2.1.4 數據驅動
- 2.1.5 雙線程下的界面渲染
- 2.2 程序與頁面
- 2.3 組件
- 2.4 API
- 2.5 事件
- 2.6 兼容
- 3. 應用設計
- 3.1 Flex布局
- 3.2 界面常見的交互反饋
- 3.3 發起HTTPS網絡通信--wx.request
- 3.4 微信登錄
- 3.5 本地數據緩存
- 3.6 設備能力
- 4. 小程序的協同工作和發布
- 4.1 協同工作
- 4.2 用戶體驗審視
- 4.3 發布
- 4.4 運營
- 5. 底層框架
- 5.1 雙線程模型
- 5.2 組件系統--Exparser框架
- 5.3 原生組件
- 5.4 小程序與客戶端通信原理
- 6. 運行和性能優化
- 6.1 啟動--代碼加載
- 6.2 頁面準備
- 6.3 數據通信
- 6.4 視圖層渲染
- 6.5 原生組件通信
- 7. 小程序基礎庫的更新迭代
- 8. 微信開發者工具
- 騰訊云支持
- wafer
- Wafer2 快速開發 Demo - PHP
- WXAPI
- api列表