您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“小程序的view模塊和service模塊怎么構成”,內容詳細,步驟清晰,細節處理妥當,希望這篇“小程序的view模塊和service模塊怎么構成”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
打開微信 web 開發者工具,然后輸入 openVendor() 便會打開 WeappVendor這個目錄,這里包含了 view 模塊和 service 模塊使用的幾個核心文件:
wcc 可執行程序,用于將 wxml 轉為 view 模塊使用的 js 代碼,使用方式為wcc xxx.wxml
wcsc 可執行程序,用于將 wxss 轉為 view 模塊使用的 css 代碼,使用方式為 wcsc xxx.wxss
WAService.js 提供 service 模塊大部分功能,下面會有詳細介紹
WAWebview.js 提供 view 模塊大部分功能,下面會有詳細介紹
view 頁面詳解
view 頁面的 template 如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <link href="https://res.wx.qq.com/mpres/htmledition/images/favicon218877.ico" rel="Shortcut Icon"> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> <script> var __webviewId__; </script> <!-- percodes --> <!--{{WAWebview}}--> <!--{{reportSDK}}--> <!--{{webviewSDK}}--> <!--{{exparser}}--> <!--{{components_js}}--> <!--{{virtual_dom}}--> <!--{{components_css}}--> <!--{{allWXML}}--> <!--{{eruda}}--> <!--{{style}}--> <!--{{currentstyle}}--> <!--{{generateFunc}}--> </head> <body> <div></div> </body> </html>
其中 <!-- percodes --> 會在 dev 模式開啟后被替換為一個時間錨點,例如:
<script>var pageFrameStartTime = new Date();</script>
<!--{{WAWebview}}--> 會被 WAWebview.js 內代碼替換
<!--{{WAWebview}}--> 到 <!--{{generateFunc}}--> 之間暫時沒有被使用到
<!--{{generateFunc}}--> 會被 wcc 命令生成后的 js 代碼替換
除了上面這些,頁面上還會被插入頁面和應用的 style 標簽,如:
<link rel="stylesheet" type="text/css" href="index.wxss">
這里的 wxss 文件包含的是原始 wxss 文件轉換后的 css
以及生成 DOM 的啟動腳本:
<script> document.dispatchEvent(new CustomEvent("generateFuncReady", { detail: { generateFunc: $gwx('./page/index.wxml') } })) </script>
WAWebview.js 文件中的各個模塊(行號為 jsbeautify 之后代碼行號,開發者工具版本:092300):
1-77 行: WeixinJSBridge 對象兼容層,這個大概只會在調試時用到,因為開發時和運行時頁面都會被后臺以注入的方式添加 WeixinJSBridge 這個對象。我們可以通過這段代碼看到它暴露的方法: invoke invokeCallbackHandleron publish subscribe subscribe subscribeHandler。
78-235 行:Reporter 對象,它的作用就是發送錯誤和性能統計數據給后臺
236-596 行:wx 對象,頁面的核心之一,一方面封裝 WeixinJSBridge 的 invokeMethod 方位為易于調用的形式(例如 redirectTo, navigateTo等),另一方面封裝 WeixinJSBridge 回調方法,調用者可以使用wx.onAppDataChange(callback) 添加數據變更的回調函數,***提供wx.publishPageEvent 發送頁面事件到后臺
607-1267 行:wxparser 對象,提供 dom 到 wx element 對象之間的映射操作,提供元素操作管理和事件管理功能
1268-1285 行:轉發 window 上的 animation 和 transition 相關的動畫事件到 exparser
1286-1313 行:訂閱并轉發 WeixinJSBridge 提供的全局事件到 exparser
1324-1345 行:轉發 window 上的 error 以及各種表單事件到 exparser
1347-3744 行:使用 exparser.registerBehavior 和exparser.registerElement 方法注冊各種以 wx- 做為標簽開頭的元素到 exparser
3744-4498 行:virtual dom 渲染算法實現,提供 diff apply render 等方法,該模塊接口基本與 virtual-dom 一致,這里特別的地方在于它所 diff 和生成的并不是原生 DOM,而是各種模擬了 DOM 接口的 wx element 對象
4599-4510 行:插入默認樣式到頁面
從頁面 data 到 dom 的主要流程如下:
var vtree var rootNode document.addEventListener("generateFuncReady", function(e) { var generateFunc = e.detail.generateFunc; wx.onAppDataChange(function(obj) { // 合并 data 到現有 data DataStore.setData(obj.data) // 生成 virtual dom 的 javascript plain object var props = generateFunc(DataStore.getData()) // ***次渲染 if (obj.options.firstRender) { vtree = createVirtualTree(props, true) rootNode = vtree.render() rootNode.replaceDocumentElement(document.body) wx.initReady() } else { var other_vtree = createVirtualTree(props, false) var patches = vtree.diff(other_vtree) patches.apply(rootNode) vtree = other_vtree document.dispatchEvent(new CustomEvent("pageReRender", {})); } }) })
上面的 DataStore 對象提供合并和獲取當前頁面 data 對象的功能,其實現如下:
var DataStore = (function() { var data = {} return { getData: function() { return data }, setData: function(e) { for (var t in e) { for (var n = (0, parsePath)(t), o = data, a = void 0, s = void 0, c = 0; c < n.length; c++) Number(n[c]) === n[c] && Number(n[c]) % 1 === 0 ? Array.isArray(o) || (a[s] = [], o = a[s]) : "[object Object]" !== Object.prototype.toString.call(o) && (a[s] = {}, o = a[s]), s = n[c], a = o, o = o[n[c]]; a && (a[s] = e[t]) } } } })() // 解析 key 為 data 內對象的路徑字符串 function parsePath(e) { for (var t = e.length, n = [], i = "", r = 0, o = !1, a = !1, s = 0; s < t; s++) { var c = e[s]; if ("\\" === c) s + 1 < t && ("." === e[s + 1] || "[" === e[s + 1] || "]" === e[s + 1]) ? (i += e[s + 1], s++) : i += "\\"; else if ("." === c) i && (n.push(i), i = ""); else if ("[" === c) { if (i && (n.push(i), i = ""), 0 === n.length) throw new Error("path can not start with []: " + e); a = !0, o = !1 } else if ("]" === c) { if (!o) throw new Error("must have number in []: " + e); a = !1, n.push(r), r = 0 } else if (a) { if (c < "0" || c > "9") throw new Error("only number 0-9 could inside []: " + e); o = !0, r = 10 * r + c.charCodeAt(0) - 48 } else i += c } if (i && n.push(i), 0 === n.length) throw new Error("path can not be empty"); return n }
可以看到,每次 data 變化之后,小程序就會開始整個頁面的 diff patch 過程。
對于原生實現的組件, exparser 會在監視到數據變化后發送對應事件到 WeixinJSBridge。
service 頁面詳解
service 頁面會被被拼接為以下的樣子:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link href="https://res.wx.qq.com/mpres/htmledition/images/favicon218877.ico" rel="Shortcut Icon"> <script> var __wxAppData = {} var __wxRoute var __wxRouteBegin </script> <script>var __wxConfig = {"pages":["page/index"], // app 相關各種配置 }</script> <script src="http://70475629.appservice.open.weixin.qq.com/asdebug.js"></script> <script src="http://70475629.appservice.open.weixin.qq.com/WAService.js"></script> <script src="http://70475629.appservice.open.weixin.qq.com/app.js"></script> <script> __wxRoute = 'page/index'; __wxRouteBegin = true </script> <script src="http://70475629.appservice.open.weixin.qq.com/page/index.js"></script> </head> <body> <script> window._____sendMsgToNW({ sdkName: 'APP_SERVICE_COMPLETE' }) </script> </body> </html>
除了配置和開發者編寫的頁面、app.js,頁面還在加載了 asdebug.js 和 WAService.js 兩個文件。
asdebug.js 文件位于 nwjs 項目目錄下,路徑為app/dist/weapp/appservice/asdebug.js。 它包含了兩個部分,一個是 WeixinJSBridge 針對 service 模塊的實現,另一塊是一些方便命令使用的接口, 例如:help() 會告訴你一些可用的函數:
該文件只會在開發者工具內被引入,如果小程序在微信內運行,應該會由微信底層提供 WeixinJSBridge。
WAService 負責 service 模塊的一些核心邏輯,它包含以下部分 (行號為 jsbeautify 之后代碼行號,開發者工具版本:092300):
1-78 行: 跟 WAWebview.js 一樣的 WeixinJSBridge 兼容模塊
79-245 行: 跟 WAWebview.js 一樣的 Reporter 模塊
246-1664 行:比 WAWebview.js 中 wx 功能更為豐富 wx 接口模塊
1665-2304 行:appServiceEngine 模塊,提供 Page,App,GetApp 接口
2305-2360 行: 為 window 對象添加 AMD 接口 require define
現在的 WAService 還有有很多地方依賴 window 對象,所以很有可能它在微信中和開發者工具內一樣,依然運行于 webview 標簽之內。
讀到這里,這篇“小程序的view模塊和service模塊怎么構成”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。