网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網

微信小程序 App() 和 Page() 函數作用

發布時間:2021-06-01 08:42 所屬欄目:小程序開發教程

在微信開發者工具中,編譯運行你的小程序項目,然后打開控制臺,輸入 document 并回車,就可以看到小程序運行時,WebView 加載的完整的 page-frame.html,如下圖:

063ae10a5f8524d17436f9eefacad11f6d7650a8

通過分析這個 HTML 文件,我們可以得到小程序的啟動執行流程大致如下:

f8765bd5baa57613f0a172fd5d97558a095280d1

此圖來自上述文章,我們這里不再重復贅述這些流程,下面我們來看一下其中的 App() 和 Page() 的細節。這兩個函數在小程序框架 WAService.js 中定義,并在 app.js 和每個頁面的 page.js 中進行調用實例化。

在微信開發者工具的控制臺中執行 openVendor() 方法,可以打開小程序框架所在目錄,如下:

/Users/用戶名/Library/Application Support/微信web開發者工具/WeappVendor/基礎庫版本號目錄

本文以 1.9.94 基礎庫為例進行分析。WAService.js 文件的結構如下:

;(function(global) {

    // WeixinJSBridge 的定義和加載

    // NativeBuffer 的定義和加載

    // wxConsole 的定義和加載

    // WeixinWorker 的定義和加載

    // Reporter 的定義和加載

    // __appServiceSDK__ 的定義和加載

    wx = __appServiceSDK__.wx,

    // exparser 的定義和加載

    // __virtualDOM__ 的定義和加載

    // __appServiceEngine__ 的定義和加載

    Page = __appServiceEngine__.Page,
    Component = __appServiceEngine__.Component,
    Behavior = __appServiceEngine__.Behavior,
    __webview_engine_version__ = .02,
    App = __appServiceEngine__.App,
    getApp = __appServiceEngine__.getApp,
    getCurrentPages = __appServiceEngine__.getCurrentPages,
    __createPluginGlobal = __appServiceEngine__.__createPluginGlobal,

    // __wxModule__ 的定義和加載

    definePlugin = __wxModule__.definePlugin,
    requirePlugin = __wxModule__.requirePlugin;

    // define 方法的定義

    // require 方法的定義

    global.App = App;
    global.Page = Page;
    global.Component = Component;
    global.Behavior = Behavior;
    global.__webview_engine_version__ = 0.02;
    global.getApp = getApp;
    global.getCurrentPages = getCurrentPages;
    global.wx = wx;
    global.definePlugin = __wxModule__.definePlugin;
    global.requirePlugin = __wxModule__.requirePlugin;

})(this);

我們發現,WAService.js 中定義了 WeixinJSBridge 和 wx 這兩個基礎 API 集合,同時也包含的其他一些框架核心,如 exparser,__virtualDOM__,__appServiceEngine__ 等。其中__appServiceEngine__ 提供了框架最基本的對外接口,如 App,Page,Component,Behavior 等方法;exparser 提供了框架底層的能力,如實例化組件,數據變化監聽,View 層與邏輯層的交互等;__virtualDOM__ 則起著連接 __appServiceEngine__ 和 exparser 的作用,如對開發者傳入 Page 方法的對象進行格式化再傳入 exparser 的對應方法處理。(此段分析摘自上述文章)

由上可知,本文要分析的全局函數 App() 和 Page() 是對 WAService.js 中定義的 __appServiceEngine__ 對象同名方法的引用。下面我們簡要分析一下它們的內部實現和初始化流程。

App() 和 getApp() 函數

根據微信小程序開發文檔,App() 函數用來注冊一個小程序,接收一個 object 對象參數,其指定小程序的生命周期函數等。我們從微信開發者工具的函數提示可以知道,App() 函數的聲明如下:

 

function App(options: _AppOptions): void
 

 

對于入參 object 對象(_AppOptions)的屬性說明如下:

37ce0c2a997dfe766c5bc9ce3fb127c5c0a0a537

此外,全局的 getApp() 函數可以用來獲取到小程序實例,它的聲明如下:

 

function getApp(): object

內部實現

 

在 __appServiceEngine__ 對象中,對 App 和 getApp 屬性的定義如下:

 

// 其中的 t 就是 __appServiceEngine__ 對象

var i = n(17);

Object.defineProperty(t, "App", {

enumerable: !0,

get: function() {

return i.appHolder

}

}),

Object.defineProperty(t, "getApp", {

enumerable: !0,

get: function() {

return i.getApp

}

}),

 

而這兩個屬性對應的實現分別為 appHolder() 和 getApp() 方法,定義如下:

 

l = void 0,

t.appHolder = (0, i.surroundByTryCatch)(function(e) {

l = new y(e)

}, "create app instance"),

t.getApp = function() {

return l

},
 

 

由上可知,在 appHolder() 方法中,把外部傳入的 object 對象傳給 y(...) 方法進行初始化一個小程序實例對象,并把結果賦給變量 l 緩存起來,而在 getApp() 方法中則直接 return l,返回當前小程序對象。

App 實例初始化流程

在上述 page-frame.html 中,我們知道,在 app.js 被加載完后,小程序框架會立即執行 require('app.js') 進行注冊小程序實例,即對 App() 函數進行調用(開發者已經在 app.js 中定義好了入參對象),如下:

 

<script src="./app.js"></script>

<script>require("app.js")</script>
 

 

在 App() 函數中,最終會調用 y(...) 方法進行初始化,其中 y(...) 的定義比較長,我們這里不再貼出代碼,詳情請自行查閱 WAService.js,它的處理流程如下:

  • 聲明 App.getCurrentPage 方法將被廢棄,請使用 getCurrentPages() 全局方法;

  • 綁定生命周期函數,即把外部入參對象定義的屬性綁定到小程序實例對象中,包括 onLaunch,onShow,onHide,onUnlaunch 和 onPageNotFound;

  • 綁定開發者自定義的其他屬性(包括數據和方法),并校驗屬性名是否為 “getCurrentPage”,如果是則警告;

  • 根據外部是否有定義 onError 屬性判斷是否注冊錯誤上報;

  • 檢查啟動參數(取自__wxConfig.appLaunchInfo)并依次調用 onLaunch 和 onShow 方法;

  • 注冊前后臺切換回調 onShow 和 onHide;

  • 注冊找不到頁面的回調 onPageNotFound;

  • 返回實例給 App() 函數進行緩存。

Page() 和 getCurrentPages() 函數

根據文檔,Page() 函數用來注冊一個頁面,接收一個 object 對象參數,其指定頁面的初始數據、生命周期函數、事件處理函數等。Page() 函數的聲明如下:

 

function Page(page: PageOptions): void

對于入參 object 對象(PageOptions)的屬性說明如下:

 

b8cdb8bdd7d9f8f8e863d1b0a96ea0754a97ba93
 

此外,getCurrentPages() 函數用于獲取當前頁面棧的實例,以數組形式按棧的順序給出,第一個元素為首頁,最后一個元素為當前頁面。它的聲明如下:

 

function getCurrentPages(): object[]
 

 

內部實現

同樣地,在 __appServiceEngine__ 對象中,對 Page 和 getCurrentPages 屬性的定義如下:

 

var r = n(2);

Object.defineProperty(t, "Page", {

enumerable: !0,

get: function() {

return r.pageHolder

}

}),

Object.defineProperty(t, "getCurrentPages", {

enumerable: !0,

get: function() {

return r.getCurrentPages

}

}),

 

而這兩個屬性對應的實現分別為 pageHolder() 和 getCurrentPages() 方法,定義如下:

 

var k = void 0, // 保存當前顯示的頁面(棧頂)

x = [], // 保存已加載過的頁面歷史棧數組

// 其中的 t 就是 __appServiceEngine__ 對象

t.getCurrentPage = function() {

return k

},

t.getCurrentPages = function() {

var e = [];

return x.forEach(function(t) {

e.push(t.page)

}),

e

},



M = {}, // 緩存所有已經注冊的頁面

t.pageHolder = function(e) {

if (!__wxRouteBegin) throw (0, f.error)("Page 注冊錯誤", "Please do not register multiple Pages in " + __wxRoute + ".js"),

new a.AppServiceEngineKnownError("Please do not register multiple Pages in " + __wxRoute + ".js");

__wxRouteBegin = !1;

var t = __wxRoute;

if (!A(t)) throw (0, f.error)("Page 注冊錯誤", __wxRoute + " has not been declared in app.json."),

new a.AppServiceEngineKnownError(__wxRoute + " has not been declared in app.json.");

var n = "undefined" != typeof __wxAppCode__ ? __wxAppCode__[t + ".json"] || {}: {};

if ("Object" !== (0, f.getDataType)(e)) throw (0, f.error)("Page 注冊錯誤", "Options is not object: " + JSON.stringify(e) + " in " + __wxRoute + ".js"),

new a.AppServiceEngineKnownError("Options is not object: " + JSON.stringify(e) + " in " + __wxRoute + ".js"); (0, f.info)("Register Page: " + t),

void 0 !== n.usingComponents ? (__virtualDOM__.Page(e), M[t] = exparser.Component._list[t]) : M[t] = e

},

 

 

分析上述代碼,我們可以總結 pageHolder 方法的處理流程如下:

  • 小程序在每加載一個頁面前,會先設置 __wxRouteBegin = true,用于標記防重;

  • 判斷 __wxRouteBegin 是否為 false,如果是,則拋出多次調用 Page 注冊錯誤;

  • 設置 __wxRouteBegin 為 false,避免被后續代碼被重復執行;

  • 調用 A(...) 方法檢查當前頁面是否在 app.json 中定義,如果沒有,則拋出錯誤;

  • 檢查外部入參(PageOptions)是否為 Object 對象,如果不是,則拋出錯誤;

  • 判斷當前頁面是否使用了自定義組件(對于使用了自定義組件的 Page 對象會采用不同的配置),然后緩存當前 Page 的配置到 M 對象中。

此外,我們可以發現,與 App() 不同的是,外部通過 Page() 函數傳入的(生命周期)代碼并不會在這里被執行,而是等待頁面 Ready 并進入頁面進行實例化后才執行。

頁面初始化流程

同樣地,根據 page-frame.html 的加載順序,在 app.js 被加載并執行后,小程序之后會先依次按順序加載所有的自定義組件代碼(如果有)并自動注冊。自定義組件(Component)在小程序開發中具有重要地位,它可以豐富小程序的基礎功能,擁有的能力比 Page 更強大,因此實現也更加復雜,篇幅有限,我們后續再單獨寫文章進行分析。

在加載執行完自定義組件的代碼后,小程序緊接著會依次按順序加載每個頁面的代碼,并執行 require(...) 進行頁面注冊,如下:

 


<script>__wxRoute = "pages/index/index";__wxRouteBegin = true</script>

<script>__wxAppCurrentFile__ = "pages/index/index.js"</script>

<script src="./pages/index/index.js"></script>

<script>require("pages/index/index.js")</script>

<script>

if(__wxRouteBegin) {

console.group("Tue Jun 26 2018 17:53:09 GMT+0800 (CST) page 編譯錯誤")

console.error("pages/index/index.js 出現腳本錯誤或者未正確調用 Page()")

console.groupEnd()

}

</script>

<!-- 加載注冊下一個 Page -->

 

  • 設置 __wxRoute 為當前 Page 的路徑,設置 __wxRouteBegin 為 true;

  • 設置 __wxAppCurrentFile__ 為當前加載的文件路徑;

  • 加載頁面代碼并執行進行注冊頁面(參考上述 pageHolder 的處理流程);

  • 判斷 __wxRouteBegin 是否為 false,來判斷該頁面是否被成功注冊(因為在 pageHolder方法中,成功執行是,會把 __wxRouteBegin 置為 false);

  • 依次加載其他 Page;

  • 等待頁面 Ready 和 Page 實例化,page Load 由 wx.onAppRoute 事件觸發。

在 page-frame.html 中,當 head 中的所有 JS 代碼都執行完畢后,會在 body 中觸發 DOCUMENT_READY 事件,如下:

 

<body>

<script>

if (document.readyState == 'complete') {

window.__global.alert('DOCUMENT_READY')

} else {

var fn = function(event) {

window.__global.alert('DOCUMENT_READY')

window.removeEventListener("load", fn)

}

window.addEventListener('load', fn)

}

</script>

</body>

 

在小程序框架 WAService.js 中,最終 DOCUMENT_READY 會轉化為 wx.onAppRoute 事件(邏輯待驗證),最終在 wx.onAppRoute 事件中進行頁面的實例化或者頁面切換。

PS:關于一個小程序頁面的完整初始化加載流程,我們將在下一篇文章中詳解。

總結

本文簡要地分析了 App() 、getApp() 和 Page() 、getCurrentPages() 等幾個函數的內部實現,希望能讓你更好地理解小程序實例對象和頁面的加載過程,給你實際開發帶來幫助。


易優小程序(企業版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/25893.html 復制鏈接 如需定制請聯系易優客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×