3(phonegap源碼分析)模塊定義與請求(define require)

        definerequire是貫徹整個phonegap代碼的核心函數,它們通過定義的一個匿名函數的即時調用來賦值的。事實上下面的匿名函數中省略了部分代碼,當然省略的代碼並不影響框架的主題功能,而是新版本中對原有功能的完善。

var  require,//myphonegap內部的工具函數,用來導入相關的模塊
        define;//在myphonegap註冊相關的模塊

  //通過一個立即調用的匿名函數,來給require和define賦上實際的函數
  (function(){
		var modules={};   // 模塊數組,添加模塊類似給這個對象添加了屬性,模塊名爲屬性名,模塊對象爲屬性值,或者說是鍵值對
				
		build = function(module){        //根據模塊對象構造模塊導出對象,模塊導出對象存儲在modules這個對象數組內
			var factory = module.factory;
			module.exports = {};           //給當前模塊加入了一個exports屬性
			delete module.factory;		   //刪除了module的屬性
			factory(require,module.exports,module);     //構建導出模塊,module.exports是傳出參數(實參,引用傳遞)
			return module.exports;
		}
		
		require = function(id){            //根據模塊名稱/id請求模塊對象,如果是第一次請求,就構建對象
			if(!modules[id]){
				throw "module " + id + " not found!";
			}
			return modules[id].factory?build(modules[id]):modules[id].exports;
		}
	
		define = function(id,factory){		 //定義模塊,模塊名稱、構建模塊對象的工廠方法。
			if(modules[id]){                  
				throw "module " + id + " is exist!";
			}
			modules[id] = {					//定義模塊對象,左邊的值爲屬性名,右邊的值爲傳入的參數 
				id:id,						
				factory:factory
			};
		}
  })();

        怎麼來理解這部分代碼呢?如果按其他面嚮對象語言(JAVAC++)來理解,可以把這個匿名函數當做一個類,這個類對外提供兩個外部方法,一個是require,一個是define,當然還有一個私有方法build,這個類的主要成員變量就是modules,好吧,modules,這個變量確實也沒有其他地方直接使用它了。

        modules是什麼呢,modules字面意義是模型,那這個變量就是存儲模塊對象的。由前面得知,requiredefine的功能分別爲請求和定義模塊。但是並不是所有的模塊在一開始就加載的,而模塊也並不是每次請求都重新生成的。

        所以modules就如同一個哈希表,主鍵就是模塊名,比如”myphonegap”、”myphonegap/common”,值就是相應模塊對象或模塊對象的工廠函數。先通過define對這個哈希表添加一個主鍵模塊名,和構建這個模塊的工廠方法,此時是沒有模塊對象的;如果是第一次請求該模塊,就會通過工廠函數來生成模塊,生成模塊之後對應的工廠方法會從表中刪除,而如果已經請求過的模塊就能在modules中找到對應模塊對象。

         現在來測試下,在myphonegap模塊的工廠函數中添加一個打印輸入語句,然後通過html加載這個js文件執行看結果。

  //註冊myphonegap模塊
    define("myphonegap", function(require, exports, module){
  		console.info("create myphonegap module");
          var myphonegap = {
  			Hello:function(name){
  				console.info("hello, "+name +" !");
  			}
  		};
  		
  		module.exports = myphonegap;
    });
  
    //註冊myphonegap/builder模塊
    define("myphonegap/builder", function(require, exports, module){
  		console.info("create myphonegap/builder module");
  });

        下面是HTML文件的源碼,js文件放置在html文件同級的js文件夾內。之後的例子也會通過這種方式來執行,除非要用到android的交互功能了。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script  type="text/javascript"  charset="utf-8"  src="js/myphonegap.js"></script>
</head>
<body>
<p>MYPHONEGAP  !</p>
</body>
</html>

        運行結構如圖,瀏覽器爲chrome,下面顯示的部分是它的“開發者工具”console下的內容


        這裏只執行了myphonegap模塊工廠函數的代碼,而myphonegap/builer的並沒有執行,因爲只有myphonegap模塊被請求了。

window.myphonegap = require('myphonegap');
window.myphonegap.Hello("wen");


myphonegap.js 源碼

;(function(){
  var  require,//myphonegap內部的工具函數,用來導入相關的模塊
        define;//在myphonegap註冊相關的模塊

  //通過一個立即調用的匿名函數,來給require和define賦上實際的函數
  (function(){
		var modules={};   // 模塊數組,添加模塊類似給這個對象添加了屬性,模塊名爲屬性名,模塊對象爲屬性值,或者說是鍵值對
				
		build = function(module){        //根據模塊對象構造模塊導出對象,模塊導出對象存儲在modules這個對象數組內
			var factory = module.factory;
			module.exports = {};           //給當前模塊加入了一個exports屬性
			delete module.factory;		   //刪除了module的屬性
			factory(require,module.exports,module);     //構建導出模塊,module.exports是傳出參數(實參,引用傳遞)
			return module.exports;
		}
		
		require = function(id){            //根據模塊名稱/id請求模塊對象,如果是第一次請求,就構建對象
			if(!modules[id]){
				throw "module " + id + " not found!";
			}
			return modules[id].factory?build(modules[id]):modules[id].exports;
		}
	
		define = function(id,factory){		 //定義模塊,模塊名稱、構建模塊對象的工廠方法。
			if(modules[id]){                  
				throw "module " + id + " is exist!";
			}
			modules[id] = {					//定義模塊對象,左邊的值爲屬性名,右邊的值爲傳入的參數 
				id:id,						
				factory:factory
			};
		}
  })();

  //註冊myphonegap模塊
  define("myphonegap", function(require, exports, module){
		console.info("create myphonegap module");
		var myphonegap = {
			Hello:function(name){
				console.info("hello, "+name +" !");
			}
		};
		
		module.exports = myphonegap;
  });

  //註冊myphonegap/builder模塊
	define("myphonegap/builder", function(require, exports, module) {

	});

   define("myphonegap/channel",function(require,exports,module){
	});

  //註冊myphonegap/common模塊
 	//配置對象,將公共模塊組織起來
	define("myphonegap/common",function(require,exports,module){
	});

 
	define("myphonegap/exec", function(require, exports, module) {
	});

		

  //註冊myphonegap/platform模塊
  define("myphonegap/platform", function(require, exports, module){
  });

  // 這裏省略了其它插件的註冊

  //註冊myphonegap/utils模塊
  define("myphonegap/utils", function(require, exports, module){
	});

	(function (context) {
	}(window));
  //所有模塊註冊完之後,再導入myphonegap至全局環境中
  window.myphonegap = require('myphonegap');
	window.myphonegap.Hello("wen");
	
})();




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章