自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

微信小程序架構(gòu)分析 (上)

開(kāi)發(fā) 架構(gòu)
相信不少上手試用了微信小程序開(kāi)發(fā)者工具的開(kāi)發(fā)者都會(huì)對(duì)其實(shí)現(xiàn)有些疑惑, 本文試圖對(duì)其架構(gòu)模型進(jìn)行一些解析。

 【引自第九程序的博客】相信不少上手試用了微信小程序開(kāi)發(fā)者工具的開(kāi)發(fā)者都會(huì)對(duì)其實(shí)現(xiàn)有些疑惑, 本文試圖對(duì)其架構(gòu)模型進(jìn)行一些解析。如有錯(cuò)誤之處,歡迎留言指出。

本文分為以下幾個(gè)部分:

  • 小程序調(diào)試技巧
  • 小程序主要模塊構(gòu)成
  • 小程序模塊間通信
  • 設(shè)計(jì)理念分析

小程序調(diào)試技巧

微信開(kāi)發(fā)者工具默認(rèn)禁用了右鍵打開(kāi)調(diào)試面板功能,我們可以修改開(kāi)發(fā)者工具部分代碼移除該限制。

  • 找到 app.nw 項(xiàng)目根目錄,Mac 下為/Applications/wechatwebdevtools.app/Contents/Resources/app.nw
  • 使用 js-beautify 對(duì)代碼批量格式化:
  1. cd /Applications/wechatwebdevtools.app/Contents/Resources/app.nw 
  2. find . -type f -name '*.js' -not -path "./node_modules/*" -not -path "./modified_modules/*" -exec js-beautify -r -s 2 -p -f '{}' \;  
  • 注釋掉文件 app/dist/app.js 44 行和app/dist/components/simulator/webviewbody.js 149 行preventDefault 調(diào)用。101100 版本還需要修改 package.json 文件,去掉 --disable-devtools。

執(zhí)行完以上操作就可以右鍵打開(kāi)頁(yè)面的調(diào)試面板了,需要特別注意的是,使用 view 頁(yè)面的面板后會(huì)導(dǎo)致 wxml 面板不可用,touch 事件無(wú)法響應(yīng)等種種問(wèn)題,請(qǐng)慎重使用。

通過(guò)代碼可以發(fā)現(xiàn),在配置目錄下添加 config.json 文件,然后加入{isDev:true} 可以啟用開(kāi)發(fā)者工具所謂的調(diào)試模式, 但是我在配置后程序無(wú)法正常啟動(dòng),只好暫時(shí)先放棄這種方式。

小程序主要模塊構(gòu)成

小程序自身分為兩個(gè)主要部分獨(dú)立運(yùn)行:view 模塊和 service 模塊。在開(kāi)發(fā)者工具中,它們獨(dú)立運(yùn)行于不同的 webivew tag 中。

view 模塊負(fù)責(zé) UI 顯示,它由開(kāi)發(fā)者編寫的 wxml 和 wxss 轉(zhuǎn)換后代碼以及微信提供相關(guān)輔助模塊組成。 一個(gè) view 模塊對(duì)應(yīng)一個(gè) webview 組件(也就是我們常規(guī)理解的一個(gè)頁(yè)面), 小程序支持同時(shí)多個(gè) view 存在。view 模塊通過(guò) WeixinJSBridge 對(duì)象來(lái)跟后臺(tái)通信。

service 模塊負(fù)責(zé)應(yīng)用的后臺(tái)邏輯,它由小程序的 js 代碼以及微信提供的相關(guān)輔助模塊組成。 一個(gè)應(yīng)用只有一個(gè) service 進(jìn)程,它同樣也是一個(gè)頁(yè)面(至少在開(kāi)發(fā)者工具內(nèi)如此,上線后可能運(yùn)行于 WeixinJSCore 之內(nèi)),與 view 模塊不同的是,它在程序生命周期內(nèi)后臺(tái)運(yùn)行,service 模塊通過(guò)與 view 模塊實(shí)現(xiàn)不同但接口格式一樣的 WeixinJSBridge 對(duì)象跟后臺(tái)通信。

小程序模塊間通信

 

 

(開(kāi)發(fā)者工具內(nèi)各模塊通信圖)

做過(guò)微信開(kāi)發(fā)相關(guān)的開(kāi)發(fā)者會(huì)對(duì) WeixinJSBridge 這個(gè)對(duì)象有所了解,它就是負(fù)責(zé) UI 與后臺(tái) 進(jìn)行交互的一個(gè)中間層。應(yīng)用號(hào)的 WeixinJSBridge 相比與之前的微信 webview 多出 publish 和 subscribe 兩個(gè)公共方法來(lái)發(fā)布和訂閱事件,從而進(jìn)行雙向通信。

service 模塊的 WeixinJSBridge 對(duì)象在文件app/dist/weapp/appservice/asdebug.js 中定義, view 層的 WeixinJSBridge 在文件 app/dist/inject/jweixindebug.js 中定義。 盡管兩者都使用一樣的接口以及使用 postMessage 方法與后臺(tái)通信,但是其內(nèi)部所做的事情確是完全不同的, 例如 service 模塊可以直接通過(guò) prompt 方法來(lái)通過(guò) prompt調(diào)起底層組件,而 view 層的 WeixinJSBridge 只能發(fā)送消息 (參考 H5與Native交互之JSBridge技術(shù))。

我們來(lái)看一個(gè)典型的交互流程:

1.用戶點(diǎn)擊界面觸發(fā)事件

2.對(duì)應(yīng) view 模塊接收事件后將事件封裝成所需格式后調(diào)用 publish 方法發(fā)送:

  1. WeixinJSBridge.publish('PAGE_EVENT', data) 

data 參數(shù)舉例:

  1. "data": { 
  2.   "eventName""onhidetap"
  3.   "data": { 
  4.     "target": { 
  5.       ... 
  6.     }, 
  7.     "currentTarget": { 
  8.       ... 
  9.     }, 
  10.     "type""tap"
  11.     "timeStamp": 11457, 
  12.     "touches": [ ...  ], 
  13.     "detail": { 
  14.       ... 
  15.     } 
  16.   } 
  17. }, 
  18. "options": { 
  19.   "timestamp": 1475445858336 
  20.  

3.后臺(tái)(開(kāi)發(fā)者工具內(nèi)為 nwjs 運(yùn)行環(huán)境)將數(shù)據(jù)處理后發(fā)送給 service 模塊,數(shù)據(jù)形如:

  1. "to""appservice"
  2. "msg": { 
  3.   "eventName""PAGE_EVENT"
  4.   "data": { 
  5.     "data": { 
  6.       "eventName""onhidetap"
  7.       "data": { 
  8.         "target": { 
  9.           ... 
  10.         }, 
  11.         "currentTarget": { 
  12.           ... 
  13.         }, 
  14.         "type""tap"
  15.         "timeStamp": 75329, 
  16.         "touches": [ ...  ], 
  17.         "detail": { 
  18.           ... 
  19.         } 
  20.       } 
  21.     }, 
  22.     "options": { 
  23.       "timestamp": 1475445858336 
  24.     } 
  25.   }, 
  26.   "webviewID": 0 
  27. }, 
  28. "command""MSG_FROM_WEBVIEW" 
  29.  

4.service 模塊的 WeixinJSBridge 內(nèi)回調(diào)函數(shù)依據(jù)傳來(lái)數(shù)據(jù)找到對(duì)應(yīng) view 的 page 模塊后執(zhí)行 對(duì)應(yīng)名為 eventName 指向的函數(shù)

5.回調(diào)函數(shù)調(diào)用 this.setData({hidden: true}) 改變 data,serivce 層計(jì)算該頁(yè)面 data 后向后臺(tái)發(fā)送 send_app_data 和 appdataChange 事件,具體數(shù)據(jù)格式如下:

  1. "appData": { 
  2.   "page/index": { 
  3.     ... 
  4.   } 
  5. }, 
  6. "sdkName""send_app_data"
  7. "to""backgroundjs"
  8. "comefrom""webframe"
  9. "command""COMMAND_FROM_ASJS"
  10. "appid""touristappid"
  11. "appname""chat"
  12. "apphash": 70475629, 
  13. "webviewID": 100000 
  14.  
  1. "eventName""appDataChange"
  2. "data": { 
  3.   "data": { 
  4.     "data": { 
  5.       "hidden"true 
  6.     } 
  7.   }, 
  8.   "options": { 
  9.     "timestamp": 1475528706311 
  10.   } 
  11. }, 
  12. "sdkName""publish"
  13. "webviewIds": [ 
  14.   0 
  15. ], 
  16. "to""backgroundjs"
  17. "comefrom""webframe"
  18. "command""COMMAND_FROM_ASJS"
  19. "appid""touristappid"
  20. "appname""chat"
  21. "apphash": 70475629, 
  22. "webviewID": 100000 
  23.  

6.后臺(tái)(文件 dist/components/simulator/webviewbody.js) 接收到appDataChange 事件數(shù)據(jù)后再將數(shù)據(jù)進(jìn)行簡(jiǎn)單封裝, ***轉(zhuǎn)發(fā)給到 view 層。 具體數(shù)據(jù)格式為: 

  1. "to""webframe"
  2. "msg": { 
  3.   "eventName""appDataChange"
  4.   "data": { 
  5.     "data": { 
  6.       "data": { 
  7.         "hidden"true 
  8.       } 
  9.     }, 
  10.     "options": { 
  11.       "timestamp": 1475528706311 
  12.     } 
  13.   }, 
  14.   "sdkName""publish"
  15.   "webviewIds": [ 
  16.     0 
  17.   ], 
  18.   "to""backgroundjs"
  19.   "comefrom""webframe"
  20.   "command""COMMAND_FROM_ASJS"
  21.   "appid""touristappid"
  22.   "appname""chat"
  23.   "apphash": 70475629, 
  24.   "webviewID": 100000, 
  25.   "act""sendMsgFromAppService" 
  26. }, 
  27. "command""MSG_FROM_APPSERVICE"
  28. "webviewID": 0, 
  29. "id": 0.10577065353216675 
  30.  

7.view 層的 WeixinJSBridge 接收到后臺(tái)的數(shù)據(jù),如果 webviewID 匹配則將 data 與現(xiàn)有頁(yè)面 data 合并, 然后就是 virtual dom 模塊進(jìn)行 diff 和 apply 操作改變 dom。

小程序模塊間消息傳遞除了界面事件和應(yīng)用數(shù)據(jù)還包括觸發(fā)原生方法、握手以及生命周期等類型, 盡管處理對(duì)象和處理方式不同,大體流程跟上面是一樣的。

view 模塊和 service 模塊的 WeixinJSBridge 都使用了 postMessage 接口 (參考MDN 文檔) 與后臺(tái)通信,但是由于該接口無(wú)法直接與 nwjs 后臺(tái)進(jìn)程通信,所以開(kāi)發(fā)者工具會(huì)將 app/dist/contentscript/contentScript.js 文件做為contentScript 注入到 view 模塊和 service 模塊所在頁(yè)面,contentScript.js 的代碼提供了 message 消息到 chrome.runtime通信接口的轉(zhuǎn)換。

微信開(kāi)發(fā)者工具擴(kuò)展了 devtools 提供了 AppData 面板,開(kāi)發(fā)者可以修改里面數(shù)據(jù)然后直接看到 view 界面的變化效果。這里修改數(shù)據(jù)后 nwjs 會(huì)將消息發(fā)送給 service 層,之后發(fā)生的事就跟上面 4 5 6 步一樣:service 傳遞消息給 nwjs,***到 view 層。

設(shè)計(jì)理念分析

小程序這樣的分層設(shè)計(jì)顯然是有意為之的,它的中間層完全控制了程序?qū)τ诮缑孢M(jìn)行的操作, 同時(shí)對(duì)于傳遞的數(shù)據(jù)和響應(yīng)時(shí)間也做到的監(jiān)控。一方面程序的行為受到了極大限制, 另一方面微信可以確保他們對(duì)于小程序內(nèi)容和體驗(yàn)有絕對(duì)的控制。

我們?cè)谛〕绦虻?js 代碼里面是不能直接使用瀏覽器提供的 DOM 和 BOM 接口的,這一方面是因?yàn)?js 代碼外層使用了局部變量進(jìn)行屏蔽,另一方面即便我們可以操作 DOM 和 BOM 接口,它們對(duì)應(yīng)的 也是 service 模塊頁(yè)面,并不會(huì)對(duì)頁(yè)面產(chǎn)生影響。

這樣的結(jié)構(gòu)也說(shuō)明了小程序的動(dòng)畫(huà)和繪圖 API 被設(shè)計(jì)成生成一個(gè)最終對(duì)象而不是一步一步執(zhí)行的樣子, 原因就是 json 格式的數(shù)據(jù)傳遞和解析相比與原生 API 都是損耗不菲的,如果頻繁調(diào)用很可能損耗 過(guò)多性能,進(jìn)而影響用戶體驗(yàn)。

理解了以上機(jī)制,再對(duì) view 模塊和 service 模塊的 WeixinJSBridge 加以改造,我們便不難做到讓 小程序跑在自己的環(huán)境下,這樣就可以做些手機(jī)調(diào)試以及單頁(yè)面測(cè)試等操作。

責(zé)任編輯:龐桂玉 來(lái)源: 第九程序的博客
相關(guān)推薦

2017-06-09 12:58:20

微信小程序架構(gòu)分析

2017-06-09 10:40:00

微信小程序架構(gòu)分析

2021-06-10 10:51:27

程序基礎(chǔ)架構(gòu)

2016-11-04 10:30:17

微信小程序

2017-05-08 15:03:07

微信小程序開(kāi)發(fā)實(shí)戰(zhàn)

2016-10-20 21:02:12

微信小程序javascript

2017-01-09 10:01:49

微信小程序

2016-11-04 10:31:49

微信程序指南

2016-09-28 18:10:59

微信程序MINA

2016-11-22 11:23:52

微信小程序騰訊微信

2016-09-27 16:38:24

JavaScript微信Web

2016-09-27 15:40:58

微信程序前端

2016-11-04 10:49:48

微信小程序

2016-11-19 18:06:44

微信小程序張小龍

2016-09-27 20:36:23

微信HttpWeb

2017-06-27 10:53:32

2017-02-06 13:32:12

微信小程序思想

2018-07-26 15:16:50

小程序iPhone X甜酸

2016-12-01 17:33:52

微信

2018-09-11 10:32:07

云開(kāi)發(fā)小程序開(kāi)發(fā)者
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)