1. 程式人生 > 實用技巧 >【微信小程式開發•系列文章六】生命週期和路由

【微信小程式開發•系列文章六】生命週期和路由

>>> hot3.png

這篇文章理論的知識比較多一些,都是個人觀點,描述有失妥當的地方希望讀者指出。

整個微信小程式從開啟到關閉,整個過程可以分為很多階段或者說狀態,這一整段的過程,我們稱之為小程式的生命週期。而週期中的每種不同的狀態,到另一個狀態的過度和轉化,是需要一個觸發機制的,這種機制我們稱之為路由。

一、生命週期

先來分析一下小程式官網給的這張圖,它指的是Page的整個生命週期。要理解它,我們還是先回顧一下React.js的渲染機制。

react裡面有一個virtual DOM的概念,它實際上是把介面中的每個元素,用js實現的樹形資料結構對應起來,結構裡記錄了節點的所有資訊。我們可以把這個virtual DOM看成一個獨立的執行緒(js裡沒有真正的多執行緒),我們暫時稱它為view執行緒,它的工作就是負責介面的渲染。當virtual DOM上的資料發生變化的時候,介面的相應的部分就會跟著更新,更新機制被稱為DOM diff,這裡有篇文章詳細地分析了這種更新機制:http://calendar.perfplanet.com/2013/diff/,不過可惜的是它要翻牆才能看,後面發現segmentfault上有人把它轉成中文描述了:https://segmentfault.com/a/1190000000606216,有興趣的讀者可以閱讀一下這篇文章。

這裡簡單地介紹下:React.createClass建立的類都有一個render方法,它返回的不是真正的html程式碼,而是我們上面講到的virtual DOM,每一次渲染會直接按內部轉換關係畫到介面上,這個流程跟傳統的網頁渲染差不多。但是當要修改介面上某些元素的時候,react的效能才會真正的突顯出來,它會去呼叫setState方法,這時有內建的演算法會去比對這次操作引起的變化前後,最小的差異是什麼,然後把這個最小的差異更新到介面上。DOM diff的這篇文章講到,傳統的兩個樹形結構要分析出差異,複雜度至少要O(n^3),但react巧妙地把這個複雜度做到了接近O(n),優化了非常多,這也是它的核心演算法。

這整個東東,就是我們上面講到的“view執行緒”,它負責拿到資料後去做介面的更新,不過這個“執行緒”不處理主業務邏輯,只負責view層,用react的時候,它的內部框架已經幫我們做好了,所以react被稱為是一個view層的框架。

那麼我們還需要一個“執行緒”來處理主邏輯,這些就是我們自己要寫的主要的程式碼。微信小程式跟react一樣,也幫我們做好了這種渲染的演算法。上圖中,左側綠色的部分,可以理解為上文中的“view執行緒”,應用啟動時,他會用Page裡的data初始值去Init出一個初始的virtual DOM,當setData被呼叫的時候,MINA就會觸發我們上面討論的DOM diff的過程,自動去更新介面。這也是為什麼我們直接修改data無效的原因,一定要呼叫setData介面才會有變化。
上圖右側的“AppService執行緒”,其實就是我們說的主業務邏輯“執行緒”,我們就是跟它打交道。

下面簡述一下整個生命週期的過程:
“view執行緒”和“AppService執行緒”在Page({… })被執行時差不多同時啟動(實際上,個人理解,後者應該要先一步啟動,因為它要接收notify,純屬猜測)。前者init結束時,傳送一個notify到後者。後者在create完成後,會同時觸發Onload和Onshow回撥(至於為什麼要同時觸發兩個看起來差不多的狀態,在下方會分析到),在這兩個函式裡面對page的data做一些修改(setData),然後掛起進入等待狀態,等“view執行緒”init完,才會進行下面的流程,因為對使用者來說這個應用的直接使用方式就是介面,背後邏輯使用者不管,所以一定要等“view執行緒”準備好後,再做下面的事情才有意義。
如果Onload和Onshow有對data做修改,收到notify通知前也不會做什麼動作,直到收到通知才會把變化傳送給“view執行緒”,之後的流程裡,setData就不用等通知了,因為這個通知只是為了讓“AppService執行緒”知道“view執行緒”已經準備好了,進入可用狀態了,後面就可以隨意setData了,“view執行緒”隨時都會做出響應,一發現資料變化就會重新render然後做DOM diff操作,去更新介面。

而當用戶進入另一個頁面時(wx.nativateTo),onHide函式被觸發,頁面被切換到後臺,可以看成是掛起狀態,不會有什麼動作。而當用戶切換回來的時候(wx.navigateBack),onShow會被觸發,但onLoad不會,onLoad只會在page初始化完成時觸發一次,後面不會再進入了,所以對於只需要做一次的操作,千萬不要寫到onShow裡面,如請求頁面初始資料,要寫到onLoad裡。上面講到“AppService執行緒”初始化的時候要同時觸發onShow和onLoad,雖然字面上理解起來比較相似,但其實是不一樣的過程,觸發條件也是不一樣的。

二、路由

路由的控制邏輯主要在WAService.js裡,這個檔案,當程式在執行時,除錯工具裡可以檢視。可惜的是,這個檔案是壓縮過的,格式化之後,還是很難看懂主要的邏輯。不過上表微信官方給的也表述得比較明顯。

大概按這表介紹下路由的幾種情況。
(1)當程式開啟的時候,第一個頁面會被載入(第一個頁面,指在app.json裡的pages配置的第一項),先初始化,這時這個頁面的onLoad和onShow會被呼叫。
(2)從第一個頁面跳到其它頁面(navigateTo),這時第一個頁面的onHide會被呼叫,跳過去的其它頁面onLoad和onShow會被呼叫。
(3)如果是redirectTo跳轉,則第一個頁面被觸發的是onUnload,其它跟(2)一樣
(4)頁面返回時,前一個頁面被onUnload卸掉,返回後的頁面onShow被呼叫。從這可以看出,返回時,前一個頁面被銷燬了。
(5)tab的切換,就只有onShow和onHide,當然第一個出現頁面還有一個onLoad。
這幾個情況也比較直觀。

轉載於:https://my.oschina.net/myfcms/blog/818894