MINA MINA 是在微信中開發小程式的框架。其目標是通過儘可能簡單、高效的方式讓開發者可以在微信中開發具有原生 APP 體驗的服務。 MINA 提供了自己的視圖層描述語言 WXML 和 WXSS,以及基於 JavaScript 的邏輯層框架,核心是一個響應的數據綁定系統。整個系統分為視圖層(Vi ...
MINA
MINA
是在微信中開發小程式的框架。其目標是通過儘可能簡單、高效的方式讓開發者可以在微信中開發具有原生 APP
體驗的服務。
MINA
提供了自己的視圖層描述語言 WXML
和 WXSS
,以及基於 JavaScript
的邏輯層框架,核心是一個響應的數據綁定系統。整個系統分為視圖層(View
)和邏輯層(App Service
),併在視圖層與邏輯層間提供了數據傳輸和事件系統,可以讓開發者可以方便的聚焦於數據與邏輯上。
MINA
讓數據與視圖保持同步非常簡單。當做數據修改的時候,只需要在邏輯層修改數據,視圖層就會做相應的更新。MINA
是騰訊給微信小程式命名的框架,實際上應用的是目前業界最著名的 MVVM
模式。
wxml的真實面目
我們都知道小程式提供了很多方便快捷的自定義組件(標簽),但你知道小程式的這些組件編譯過後會渲染成什麼嗎?先說答案,其實 wxml
經過編譯後會渲染成 html
。很簡單的一點,你發現在小程式內編寫 html
標簽,最終也可以運行。
探尋
光說可能體會不到,下麵開始探尋小程式真實渲染的樣子。先看下開發者工具內 wxml
的內容,待會和真實渲染的內容做對比。
接下來一步步找到小程式 wxml
渲染完成的真實樣子,工具菜單欄點擊微信開發者工具,選擇調試微信開發者工具。打開的控制台可以調試整個微信開發者工具,用調試箭頭指向小程式內容區域,這時可以看到小程式視圖層是被嵌套在 webview
的 iframe
內。
但是當我們點開 iframe
是無法查看到裡面內容的。如果想要查看調試 webview
,只需選中 webview
打開它的調試工具即可,在控制台輸入以下代碼:
$$('webview')[0].showDevTools(true)
可以看到又打開了一個調試視窗,這裡面就是小程式視圖層渲染的真實樣子:
可以看到結構和 wxml
里的內容幾乎一模一樣,只是 topbar
變成了 wx-topbar
,view
變成了 wx-view
等。這些都是內部實現的一套對應小程式標簽的 webComponent
組件,而 webComponent
實際渲染出來還是 html
標簽。
轉換過程
轉換過程是微信開發者工具內部通過一個可執行編譯工具實現對小程式文件轉換。在微信開發者工具控制台輸入 openVendor()
會打開一個文件夾,裡面存放著微信的基礎庫及工具,在裡面可以找到 wcc.exe
、wcsc.exe
執行文件,分別對應 wxml
和 wxss
的文件轉換。
該工具可以單獨對小程式文件進行轉換,使用方法 ./wcc -d wxml文件路徑 >> 輸出路徑
。例如,將工具複製到一個文件夾內,再將一個 wxml
放入該文件夾內,命令行輸入 :
./wcc -d index.wxml >> index.js
可能有人很好奇為什麼是生成 js
文件,而不是 html
文件。原因很簡單,因為需要處理 wxml
的動態綁定數據。看看這個 js
文件生成的是什麼:
因為這些都是混淆壓縮過的代碼,基本沒有可讀性。這裡只需要註意一個函數就好,那就是 $gwx
。這是個很關鍵的函數,它的作用是生成虛擬dom樹,用於渲染真實節點。
接下來回到 webview
調試視窗,在 head
內找到這段插入的 script
標簽代碼:
有沒有很熟悉,沒錯,就是和上面轉換後的代碼是同一個東西。也就是說,我們的 wxml
文件通過編譯,最終在視圖層中執行的就是這段 js
代碼(這裡只是可以大概這麼理解,實際需要向邏輯層獲取數據才能渲染頁面)。控制台輸入 $gwx
發現這個函數存在,那麼這個函數如何生成虛擬dom呢?$gwx
函數的第一個參數接收一個路徑參數,這個路徑就是 wxml
文件路徑,此時在控制台輸入:
let generateFunc = $gwx('./pages/index/index.wxml')
generateFunc()
這時頁面虛擬dom就生成出來了:
單純調用 generateFunc
生成出來的虛擬dom是沒有動態綁定數據的,如果想要動態的綁定數據,在調用 generateFunc
時傳入一個數據對象。但是數據全在邏輯層里,這時就需要進行通信了。
數據通信
首先要知道小程式時運行在基礎庫之上的,但它們都是壓縮打包好的,後面找到反編譯出來的基礎庫代碼,其中最重要的就是 WAService.js
和 WAWebview.js
,它們分別是視圖層和邏輯層的核心實現。
它們之間需要一個橋梁來進行通信,那就是 JS Bridge
。JS Bridge
提供調用原生功能的介面(攝像頭,定位等),它的核心是構建原生和非原生間消息通信的通道,而且這個通信的通道是雙向的。通過 JS Bridge
的發佈訂閱方法,視圖層和邏輯層進行數據通信。
通信流程
接下來看看視圖層和邏輯層的交互流程:
wxml
轉換成對應的js
文件,等待生成虛擬dom函數$gwx
準備完成,使用dispatchEvent
通知WAWebview
。
WAWebview
監聽到generateFuncReady
事件觸發,使用WeixinJSBridge.publish
向邏輯層通信。
邏輯層處理邏輯,也就是我們平常寫的小程式
js
文件里的東西,然後通過JS Bridge
通知並返回數據給視圖層。視圖層接收到數據,將數據傳入生成虛擬dom的函數內,渲染頁面,當然小程式也有相應的diff演算法。
例如在 wxml
中綁定一個動態數據 title
,視圖層接收到數據後,重新生成虛擬dom
generateFunc({
title: '標題'
})
初始化完成後,就會走對應的其他生命周期,或者用戶觸發事件,數據都會在邏輯層處理完成後通過 JS Bridge
通知到視圖層,視圖層再次調用生成虛擬dom的函數,更新頁面。
wxss如何工作
wxss
工作原理和 wxml
差不多,都是通過工具轉換為 js
。為什麼又是轉換成 js
,因為有 rpx
單位,需要根據手機尺寸進行設置 px
。
wcsc.exe
轉換命令如下:
./wcsc -js index.wxss >> index.js
可以看到文件開頭就是對 rpx
的轉換
之後創建 style
標簽,動態添加到視圖層中
最後
附上 WAService.js 和 WAWebview.js 的代碼作為學習參考。