在 模塊化開發
開發之前,都是直接在頁面上引入 script
標籤來引用腳本的,當項目變得比較複雜,就會帶來不少問題。javascript
因而,AMD 規範就誕生了,AMD 即爲異步模塊定義,有效避免同步加載致使頁面的假死現象。RequireJS 是一個 AMD 的實現,後來還有CMD規範,玉伯的 而SeaJS 是 CMD 的一個實現,二者最大的區別就是html
RequireJS 是預加載,而sea.js 是懶加載,也就是按需加載java
什麼意思 ??jquery
好比下面的代碼數組
define(function(require,exports,module){ // do something var mod1 = require('./mod1'); // do something var mod2 = require('./mod2'); })
RequireJS 會所有找到這個模塊的依賴,並在開始執行是就加載所有的依賴,
而SeaJS 則是按需加載,直到遇到 require 纔會加載。瀏覽器
RequireJS 內部經過
Function.prototype.toString()
,而後使用正則匹配全部的require 方法,將其轉化爲app
define(['./mod1',./mod2']function(mod1,mod2)
這種方式。異步
有不少關於這兩種方式的爭吵,因爲我沒有作過較大的項目,因此對於這兩種方式在正真項目中使用的區別也不清楚。模塊化
主要接口有兩個: require
& define
,define 是模塊的定義方法,require 是模塊的使用方法。
define 的參數爲 define (id?,deps?,factory)
。第一個爲模塊ID,第2個爲依賴列表,第三個是工廠方法 。若是不定義ID,則爲匿名方法,一般狀況,模塊ID 等於模塊在工程的路徑。deps 和 factory 有約定,deps 數組有多少個元素,factory 就會有多少個形參,形參對於與依賴模塊工廠函數執行後的返回值。函數
define ("id",["mod1","mod2"],function(mod1,mod2){ return { /// }; })
require 方法和 define 基本一致。
文件目錄
└─ use-require/ ├─ app/ │ ├─ js/ │ │ ├─ module/ │ │ │ ├─ a.js │ │ │ └─ b.js │ │ ├─ main.js │ └─ lib/ │ │ └─ require.js ├─ index.html └─ readme.md
如今,須要在 index.html 引導整個程序 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script src="./app/lib/require.js" data-main="./app/js/main"> </script> </body> </html>
引入 requirejs,並經過 data-main
申明 啓動 js 文件。
注意: data-main 指向的文件所在路徑就是 baseUrl,在這裏就是app/js ,
baseUrl 也能夠經過require.config 設置 。若是沒有經過 data-main 屬性指定 baseUrl ,也沒有經過config的方式顯示聲明 baseUrl ,那麼 baseUrl 默認爲加載requirejs的那個頁面所在的路徑
下面 b 依賴 a ,那麼就應該寫module/a
,而 main 依賴 b ,寫爲module/b
,這個路徑會和 baseUrl 拼接,與a ,b 所在的路徑無關 。有時候,你可能須要生成一個相對於模塊的URL地址。你能夠將require
做爲一個依賴注入進來,而後調用require.toUrl()
以生成該URL 。
define(["require"], function(require) { var url = require.toUrl("./style.js"); });
有時候你想避開"baseUrl + paths"的解析過程,而是直接指定加載某一個目錄下的腳本。此時能夠這樣作:若是一個module ID符合下述規則之一,其ID解析會避開常規的"baseUrl + paths"配置,而是直接將其加載爲一個相對於當前HTML文檔的腳本:
注意是 相對於 HTML 文檔,由於 js腳本是會被插入到 html 文檔中執行的 。
通常來講,最好仍是使用baseUrl及"paths" config去設置module ID。它會給你帶來額外的靈活性,如便於腳本的重命名、重定位等。 同時,爲了不凌亂的配置,最好不要使用多級嵌套的目錄層次來組織代碼,而是要麼將全部的腳本都放置到baseUrl中,要麼分置爲項目庫/第三方庫的一個扁平結構,以下:
└─ project/ ├─ js/ │ ├─ app/ │ │ └─ sub.js │ ├─ lib/ │ │ ├─ jquery.js │ │ └─ require.js │ └─ app.js ├─ index.html └─ readme.md
下面天然就順利成章
申明模塊a
define(function() { 'use strict'; return { name: "hello , i am a" } })
模塊 b
define(["module/a"], function(a) { 'use strict'; var aName = a.name; var name = "hello i am b"; return { sayHello: function() { console.log(name + " my brother is " + aName); } } })
在模塊b 裏面依賴模塊a 。
main.js
require(["module/b"], function(b) { 'use strict'; b.sayHello(); })
看看效果
若是使用 require.config()
配置呢?
將上面的目錄複製一份,命名 use-require-config
,目錄結構徹底一致
main.js
requirejs.config({ baseUrl: './app/js/module' }) require([".b"], function(b) { 'use strict'; b.sayHello(); })
在這裏,將配置放在 main.js 裏面,等會兒會講若是不放在它裏面會又什麼問題。
模塊 b 依賴 於 a
define(["./a"], function(a) { 'use strict'; var aName = a.name; var name = "hello i am b"; return { sayHello: function() { console.log(name + " my brother is " + aName); } } })
因爲將
baseUrl
設置爲app/js/module
,因此這裏依賴a
就能夠直接寫a
在這裏,我使用./a
, 與直接寫a
如出一轍,仍是使用baseUrl+ moduleName
`來尋找模塊路徑。
若是不將 requirejs.config
放在main中,而是另外在引入一個script 節點來放置 呢
<body> <script src="./app/lib/require.js" data-main="./app/js/main"> </script> <script> requirejs.config({ baseUrl: './app/js/module' }) </script> </body>
在瀏覽器運行
發現報錯了,怎麼回事呢?
看它尋找 main.js 的路徑
file:///E:/HFLib/module/code/use-require-config/app/js/module/main.js
是 baseUrl + main.js。 這說明,配置的 baseUrl 覆蓋了爲 data-main 配置的路徑
也就是說,一旦使用requirejs.config 來配置 baseUrl,那麼全部的路徑都會以 baseUrl 爲基準。
因此,data-main 應改成: ..\main
,注意這裏必需要使用反斜槓,正斜槓拼接老是會出現問題。
經過這樣就能夠解決 data-main 和 requirejs.config() 的衝突了 。
paths 和 shim 。
當模塊名過長是,require.js 爲咱們提供了路徑 paths 的方式 。
理想情況下,每一個加載的腳本都是經過define()來定義的一個模塊;但有些"瀏覽器全局變量注入"型的傳統/遺留庫並無使用define()來定義它們的依賴關係,你必須爲此使用shim config來指明它們的依賴關係。
這是個人文件目錄
index.html
<body> <script src="./app/lib/require.js" data-main="./app/main"> </script> </body>
main.js
requirejs.config({ paths: { jQuery: 'lib/jQuery' }, shim: { 'jQuery': { exports: '$' } } }) require(['jQuery'], function($) { 'use strict'; console.log($); })
能夠看到,已經順利注入了 jQuery 依賴。
require.js 中還有不少配置和用法,我用的就比較少,就簡單介紹到這裏。
下來,我要實現一個簡化的模塊加載器,相似於 require.js.
太晚了 。
就在 實現一個本身的模塊加載器(二)中實現一個相似 require.js 的Demo 吧 。