前言
了解微信小程序原理,感覺可以幫助自己更好理解為什么有些問題是這樣那樣的妙蔗,整理了下,以前發(fā)現(xiàn)的一些問題也更能理解了
基本架構(gòu)
小程序的基本架構(gòu)由View視圖層、APPServices邏輯層組成夹孔,兩者之間是相對獨立,它們之間是通過微信的JSBridge來進行通信和協(xié)作的析孽。
渲染層的界面使用了WebView 進行渲染搭伤;邏輯層采用JsCore線程運行JS腳本。一個小程序存在多個界面袜瞬,所以渲染層存在多個WebView線程怜俐,這兩個線程的通信會經(jīng)由微信客戶端(下文中也會采用Native來代指微信客戶端)做中轉(zhuǎn),邏輯層發(fā)送網(wǎng)絡請求也經(jīng)由Native轉(zhuǎn)發(fā)邓尤。
運行機制:
小程序啟動可以分為兩種情況拍鲤,一種是冷啟動,一種是熱啟動汞扎。
- 冷啟動:如果用戶首次打開季稳,或小程序銷毀后被用戶再次打開,此時小程序需要重新加載啟動澈魄,即冷啟動景鼠。
- 熱啟動:如果用戶已經(jīng)打開過某小程序,然后在一定時間內(nèi)再次打開該小程序痹扇,此時小程序并未被銷毀铛漓,只是從后臺狀態(tài)進入前臺狀態(tài),這個過程就是熱啟動帘营。
小程序銷毀時機
通常票渠,只有當小程序進入后臺一定時間,或者系統(tǒng)資源占用過高芬迄,才會被銷毀问顷。具體而言包括以下幾種情形:
- 當小程序進入后臺,可以維持一小段時間的運行狀態(tài),如果這段時間內(nèi)都未進入前臺杜窄,小程序會被銷毀肠骆。
- 當小程序占用系統(tǒng)資源過高,可能會被系統(tǒng)銷毀或被微信客戶端主動回收塞耕。
- 在 iOS 上蚀腿,當微信客戶端在一定時間間隔內(nèi)連續(xù)收到系統(tǒng)內(nèi)存告警時,會根據(jù)一定的策略扫外,主動銷毀小程序莉钙,并提示用戶 「運行內(nèi)存不足,請重新打開該小程序」筛谚。具體策略會持續(xù)進行調(diào)整優(yōu)化磁玉。
- 建議小程序在必要時使用 wx.onMemoryWarning 監(jiān)聽內(nèi)存告警事件,進行必要的內(nèi)存清理驾讲。
更新機制
未啟動時更新
開發(fā)者在管理后臺發(fā)布新版本的小程序之后蚊伞,如果某個用戶本地有小程序的歷史版本,此時打開的可能還是舊版本吮铭。微信客戶端會有若干個時機去檢查本地緩存的小程序有沒有更新版本时迫,如果有則會靜默更新到新版本∥缴危總的來說掠拳,開發(fā)者在后臺發(fā)布新版本之后,無法立刻影響到所有現(xiàn)網(wǎng)用戶纸肉,但最差情況下碳想,也在發(fā)布之后 24 小時之內(nèi)下發(fā)新版本信息到用戶。用戶下次打開時會先更新最新版本再打開毁靶。
啟動時更新
小程序每次冷啟動時,都會檢查是否有更新版本逊移,如果發(fā)現(xiàn)有新版本预吆,將會異步下載新版本的代碼包,并同時用客戶端本地的包進行啟動胳泉,即新版本的小程序需要等下一次冷啟動才會應用上拐叉。
如果需要馬上應用最新版本,可以使用 wx.getUpdateManager API 進行處理扇商。
View視圖層
由WXML凤瘦、WXSS兩部分組成
AppServices邏輯層
1、App( ) 小程序的入口案铺;
2蔬芥、Page( ) 頁面的入口
3、提供豐富的 API,如微信用戶數(shù)據(jù)笔诵,掃一掃返吻,支付等微信特有能力。
4乎婿、每個頁面有獨立的作用域测僵,并提供模塊化能力。
5谢翎、數(shù)據(jù)綁定捍靠、事件分發(fā)、生命周期管理森逮、路由管理運行環(huán)境
邏輯層的運行環(huán)境
IOS - JSCore
Android - X5 JS解析器
DevTool - nwjs Chrome 內(nèi)核
setData機制
小程序的視圖層目前使用 WebView 作為渲染載體榨婆,而邏輯層是由獨立的 JavascriptCore 作為運行環(huán)境。在架構(gòu)上吊宋,WebView 和 JavascriptCore 都是獨立的模塊纲辽,并不具備數(shù)據(jù)直接共享的通道。當前璃搜,視圖層和邏輯層的數(shù)據(jù)傳輸拖吼,實際上通過兩邊提供的 evaluateJavascript 所實現(xiàn)。即用戶傳輸?shù)臄?shù)據(jù)这吻,需要將其轉(zhuǎn)換為字符串形式傳遞吊档,同時把轉(zhuǎn)換后的數(shù)據(jù)內(nèi)容拼接成一份 JS 腳本,再通過執(zhí)行 JS 腳本的形式傳遞到兩邊獨立環(huán)境唾糯。
而 evaluateJavascript 的執(zhí)行會受很多方面的影響怠硼,數(shù)據(jù)到達視圖層并不是實時的
簡單理解的話,如用戶在視圖層觸發(fā)一些交互移怯,底層代碼的邏輯是:
View視圖層->JSBridge->APPServices邏輯層->JSBridge->View視圖層
這種復雜的交互邏輯香璃,在一些強交互場景下就會顯得卡頓,所以原生組件出現(xiàn)舟误。
原生組件的邏輯是
原生組件->APPServices邏輯層->原生組件
因為原生組件本身是有客戶端控制(可以理解為JSBridge)葡秒,所以簡化了代碼交互的邏輯。
由于原生組件脫離在 WebView 渲染流程外嵌溢,所以在使用原生組件時眯牧,跟小程序普通組件存在一些差異:
- 原生組件的層級是最高的,所以頁面中的其他組件無論設置
z-index
為多少赖草,都無法蓋在原生組件上学少。- 后插入的原生組件可以覆蓋之前的原生組件。
- 原生組件還無法在 中使用秧骑。
- 基礎庫 2.4.4 以下版本版确,原生組件不支持在 scroll-view扣囊、swiper、movable-view 中使用阀坏。
- 部分CSS樣式無法應用于原生組件如暖,例如:
- 無法對原生組件設置 CSS 動畫
- 無法定義原生組件為
position: fixed
- 不能在父級節(jié)點使用
overflow: hidden
來裁剪原生組件的顯示區(qū)域
- 原生組件的事件監(jiān)聽不能使用
bind:eventname
的寫法,只支持bindeventname
忌堂。原生組件也不支持 catch 和 capture 的事件綁定方式盒至。 - 原生組件會遮擋 vConsole 彈出的調(diào)試面板。 在工具上士修,原生組件是用web組件模擬的枷遂,因此很多情況并不能很好的還原真機的表現(xiàn),建議開發(fā)者在使用到原生組件時盡量在真機上進行調(diào)試棋嘲。
參考