微信小程序基本環境
參考 https://www.zhihu.com/question/50920642
1. 提供了JavsScript運行環境,由JavaScript編寫的業務代碼完成邏輯層的處理
2. 通過數據傳輸接口(注冊Page時的data屬性及后續的setData方法調用)將邏輯層的數據傳輸給視圖層
3. 視圖層由WXML語言編寫的模板通過“數據綁定”與邏輯層傳輸過來的數據merge成展現結果並展現
4. 視圖的樣式控制由WXSS語言編寫的樣式規則進行配置
再分別來看這4點各自的細節問題:
1. 提供了JavsScript運行環境,由JavaScript編寫的業務代碼完成邏輯層的處理
JavaScript運行環境是什么?
開發文檔Q&A( https://mp.weixin.qq.com/debug/wxadoc/dev/qa/qa.html)中這句已給出,JS運行環境是在JsCore里:
為什么腳本內不能使用window等對象頁面的腳本邏輯在是在JsCore中運行
2. 通過數據傳輸接口(注冊Page時的data屬性及后續的setData方法調用)將邏輯層的數據傳輸給視圖層
數據在邏輯層與視圖層間如何傳輸?
視圖為純native渲染,故位於native端。
而邏輯層如上所述,是跑在JsCore中的JavaScript代碼。
有了JsCore,微信小程序框架的native端與js端就可以通過JsCore來相互通信了。於是,微信小程序框架的native端與js端可以約定好通信協議/規范,再把js端通過此通信協議/規范與native通信的部分封裝並暴露接口為API(最上層的傳輸或說設置數據的API也就是上面說的注冊Page時的data屬性與后續的setData方法),這樣邏輯層的業務代碼就可以實現向視圖層傳輸數據了。
(對native其他API的調用也用類似的方法即能走通)
3. 視圖層由WXML語言編寫的模板通過“數據綁定”與邏輯層傳輸過來的數據merge成展現結果並展現
視圖層與數據如何merge為展現結果並展現?
首先看WXML語言提供的接口,發現它:
- 類似於html/xml,用標簽方式來描述視圖
- 類似angular/vue,通過指令(標簽的特殊屬性)與雙大括號來實現模板的增強功能,使模板與數據merge為結果標簽
- 但細看發現,指令其實很簡單,只提供了用於循環列表的wx:for指令,與用於控制邏輯的wx:if,wx:else,wx:elif指令
- 雙大括號內支持簡單的表達式,表達式中的變量即邏輯層輸入的數據
- 每次邏輯層更新數據,視圖層會相應更新merge並更新渲染
native端讀取WXML模板文件,再根據邏輯層傳來的數據將其中的指令與雙大括號處理解析(可根據大括號表達式從數據中取值並計算,再以對表達式值進行循環與判斷便可相應解除wx:for,wx:if指令),生成與數據merge后、可以表征最終展現內容的標簽串,
再以解析xml的方式解析標簽為帶有屬性的節點樹,並對應節點樹中各節點相應創建native中的視圖元素(可能為系統組件、也可能為微信框架中的視圖組件)、設置相應屬性、維護為正確的父子關系即可。
邏輯層數據更新時,也更新相應屬性即可。
當然實際處理中,要考慮的因素要多許多,也會做許多優化,但基本思路應大致如此。
4. 視圖的樣式控制由WXSS語言編寫的樣式規則進行配置
樣式如何匹配與設置?
構建出各視圖元素后,仍由native讀取WXSS文件,用簡單字符串匹配即可將其解析為一對一對的"選擇器-規則"對,規則內即為屬性鍵值。之后再對各視圖元素與"選擇器-規則"對中的選擇器進行匹配,匹配成功設置相應屬性值(還要考慮全局樣式與頁面樣式及style屬性樣式中的優先級)即可
如何使用css樣式對native元素進行布局?
最基本的flex布局可以由facebook的css-layout來完成( GitHub - facebook/css-layout: A subset of CSS (specifically flex-box) re-implemented as a stand alone project for use primarily on mobile. Used by react-native)
另外,事件方面,native接收到用戶事件后,必要時通過JsCore反向與其內運行的js進行通信,將事件數據傳遞給js端的框架,再由js端框架調起相應回調即可。
========================
使用了前端技術棧 JavaScript/WXML/WXSS。但和常規的前端開發又有一些區別:
- JavaScript: 微信小程序的 JavaScript 運行環境即不是 Browser 也不是 Node.js。它運行在微信 App 的上下文中,不能操作 Browser context 下的 DOM,也不能通過 Node.js 相關接口訪問操作系統 API。所以,嚴格意義來講,微信小程序並不是 Html5,雖然開發過程和用到的技術棧和 Html5 是相通的。
- WXML: 作為微信小程序的展示層,並不是使用 Html,而是自己發明的基於 XML 語法的描述。
- WXSS: 用來修飾展示層的樣式。官方的描述是 “ WXSS (WeiXin Style Sheets) 是一套樣式語言,用於描述 WXML 的組件樣式。WXSS 用來決定 WXML 的組件應該怎么顯示。” “我們的 WXSS 具有 CSS 大部分特性...我們對 CSS 進行了擴充以及修改。”
微信小程序最大的好處是不需要做設備適配,只要微信能運行,小程序就能運行。小程序雖然是一個封閉形態下的前端開發技術,但借助微信的巨大影響力,幾乎所有人都在往里面沖。
運行時會有兩個JS線程:數據線程和渲染線程
數據線程 (headless js):
- 運行你的JS,把data 發去渲染線程 (App/Page生成時是深拷貝,以后是每次diff。BTW注入渲染線程時用的是 evaluateJavascript )
- 接受Event和其他東西,發射新的data
- 運行企鵝自己的代碼,讓你可以用 wx.* API
渲染線程 (webview):
- 運行你寫的 wxml,接受data返回VDOM (wxml會被編譯成一個類似react的函數component的東西)
- 把VDOM中的一些component,如text,在webview內渲染成DOM
- 另一些component,如map,被發去不知哪里,渲染成native view
---
總體上是個想學PWA又不肯放權的尷尬產物。
實現上和 react-native 更類似,不過渲染不是純dom也不是純native,是雜種的。這有一些后果:
- wxss(沒有,無法)支持CSS的多級選擇器等。可能是因為性能,以及讓css layout兼容 “完整的” CSS太難
- 樣式不統一,比如android 的text-input在選中和非選中狀態字體有微妙不同。可能對企鵝來說做得像ios就是好UI了。
