(注: 本文中所列微信小程序工具代碼,並不是爲微信小程序原始代碼,而是學習概括的示意代碼)json
在學習開發微信小程序中, 分析總結了最近版本微信小程序模塊化的函數 require的加載與初始化模塊機制,
概括說來,小程序JS模塊加載可分爲兩大步驟:
一,JS模塊加載
二,JS模塊初始化
具體以下:小程序
微信小程序運行的架構,基本上是瀏覽器 -> HTTP本地服務 -> 雲端服務, HTTP本地服務用來讀取本地文件或者代理雲端的文件資源。
讀取項目中JS文件, 是由HTTP本地服務取本地存儲的腳本文件.微信小程序
既然採用了這種架構,那微信小程序就相似瀏覽器那樣,藉助一個HTML頁面來引用加載全部的JS文件。(注:這同NODE.JS的方式區別)
在小程序開發開具的HTTP服務部分代碼,能夠看到這個服務幹了這件事情:
微信小程序包目錄下面全部.js文件, 會按<script src="../xxx.js"> 方式插入生成一個HTML文件,而後相似瀏覽器方式加載.瀏覽器
但是事情並未結束,這種方式一加載,全部js文件都會當即執行,亂糟糟生成一團,怎麼可能..那require函數又拿來幹什麼呢?
原來這兒,HTTP服務在返回.JS文件內容的,給腳本內容包裝上了一層: define函數服務器
代理服務部分代碼: (projectManager.js) function getScripts(projInfo, callback) { ... fs.readFile(fname, 'utf8', function(err, scripts) { .... scripts = 'define("' + moduleName + '", function(require, module, exports, ' + noBrowserStr + '){ ' + scripts + '\n});', needRequire && (scripts += 'require("' + moduleName + '")'), //page頁面js文件,會添加上require本身,加載後當即初始化。 ..... callback(null, scripts) //scripts串內容做爲HTTP GET的返回
define函數很是簡單,大體以下:微信
...... var ...... moduleList = {}; define = function(moduleName, factory) { //define是全局函數,每一個JS文件都默認會調用. moduleList[moduleName] = { status: status1, factory: factory } };
從上面代碼看出,,這樣一來,每加載一個JS文件,只是將其文件名與腳本內容串加入了內存中的一個變量保存,並未執行。 注意,這就與普通的HTML 腳本引用加載當即執行徹底不一樣了.架構
接下來,就輪到微信小程序的require函數出場了。app
先看看微信小程序require函數的定義:模塊化
.... require = function(moduleName) { .... var module = moduleList[moduleName]; //define函數調用時爲moduleList賦的值 ..... if (module.status === status1) { //若是未初始化,則初始化 var factory = module.factory, //這個factory就是這個JS文件的腳本. obj = { exports: {} }, u = void 0; factory && (u = factory(o(moduleName), obj, obj.exports)), module.exports = obj.exports || u, module.status = status2 } return module.exports }
從上面能夠看出, require函數只是經過模塊名,從內存中獲取腳本內容執行,並置標誌以保證只執行一次.函數
再精簡一下:
require --調用-> factory --->模塊中可能再require另外一個模塊...
這樣就是一個典型的遞歸結構。
所謂頁面JS,,就是在app.json中註冊的page的js, 它們並無被其它JS require方式引用,
那麼它們在何時初始化?
回到以前本地代理服務器的代碼,留意下面一點:
代理服務部分代碼: (projectManager.js) function getScripts(projInfo, callback) { ... fs.readFile(fname, 'utf8', function(err, scripts) { .... //page頁面js文件,needRequire值爲TRUE,會添加上require本身 needRequire && (scripts += 'require("' + moduleName + '")'), .....
原來它們仍是使用require函數初始化,並且是加載後當即執行。
目前一般微信小程序代碼結構不會太複雜,但隨着產品的發展,需求的增長, 代碼結構可能愈來愈複雜,愈來愈注意模塊化.同時,如何將舊有JS模塊在微信小程序中重用,這也是個重要話題。 因此深刻理解微信小程序的JS模塊化機制也是頗有價值的.