源碼地址:http://www.wcscj.xyz:3000/wcs/requirejs-tutorialjavascript
在一些大的項目裏面一般會有不少個js文件,一般使用<script>標籤逐個加載。另一切js的文件可能會依賴於其餘的文件,這裏咱們須要保證被依賴的文件先於當前的文件加載。好比說jquery,不少的庫都依賴核心的jquery模塊。咱們經過模擬真實的環境來說解requirejs的加載。css
purchase.jshtml
function purchaseProduct() { console.log('Function :purchaseProduct') var credis = getCredits(); if(credis>0){ reserveProduct(); return true; } return false; }
products.jsjava
function purchaseProduct() { console.log('Function :purchaseProduct') var credis = getCredits(); if(credis>0){ reserveProduct(); return true; } return false; }
credits.jsjquery
function getCredits(){ console.log('Function : getCredits'); var credits = "100"; return credits }
在這個例子裏面,咱們試圖購買一個產品。首先檢查是否有足夠的信用可用於購買產品。而後,在確認信用以後保留產品。git
如今咱們經過main.js經過調用 purchaseProduct()來初始化代碼。以下所示github
**main.js **redis
var result=purchaseProduct();
在上面的三個文件中,咱們能夠發現purchase.js依賴credits.js和products.js模塊。因此credits.js和products.js必須先於調用purchaseProduct()前引入。可是咱們故意調整錯誤引入次序,會發現什麼事?bootstrap
index.html瀏覽器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="products.js"></script> <script src="purchase.js"></script> <script src="main.js"></script> <script src="credits.js"></script> </head> <body> </body> </html>
經過運行上面的html,你會發現瀏覽器並不會如預期輸出信息,而是打印了一條錯誤信息。
purchase.js:3 Uncaught ReferenceError: getCredits is not defined at purchaseProduct (purchase.js:3) at main.js:1
這是由於credits.js是在main.js以後,在咱們調用 purchaseProduct()的函數時候並無加載credits.js文件,瀏覽器找不到對應的函數的聲明。
上面僅僅是3個js的文件,而一個大型的項目當中可能存在着幾十個js的文件,你要時刻去關注每一個js文件的依賴,是否是想一想就以爲頭痛。
按照官方的解釋,RequireJS是一個javaScript文件和模塊加載器。不只可以優化瀏覽器環境。同時也能用於Rhino和Node.RequireJS不只可以異步進行模塊的加載,同時能夠定義模塊間的依賴關係,經過配置可以優化程序的運行速度以及質量。
在咱們進行項目的講解以前,您須要去github或者官網上面下載最新的requirejs文件而且放置在項目的scripts目錄下面。
假設咱們的項目結構以下圖所示
全部的javascript文件(包括RequireJS文件)都位於腳本文件夾內。main.js文件用於初始化,其餘文件包含了應用程序的業務邏輯。咱們看看script的文件如何應用到html文件當中。
<script data-main="scripts/main" src="scripts/require.js"></script>
上面的代碼段是咱們使用requireJS文件惟一須要加入的代碼。上面的代碼塊中data-main懺悔定義應用程序的入口點。在上面的案例中咱們使用main.js文件。RequireJS會利用main.js文件自動查找其餘腳本以及依賴。
如今咱們來看看加入requirejs後的main.js文件的代碼
// var result=purchaseProduct(); require(['purchase'],function(purchase){ purchase.purchaseProduct(); })
在RequireJS,全部的代碼都被封裝在require()和define()函數。上面的require函數的第一個參數指定了依賴。在咱們的示例中咱們須要調用 purchaseProduct函數,這個函數定義在purchase.js,因此咱們須要進行加載。
第二個參數是一個匿名函數,上面的代碼咱們僅加載了purchase模塊,函數函數中的purchase對應的就是purchase文件中暴露的文件。一樣的requireJS支持多個依賴的加載如:
require(['a','b','c'],function(a,b,c))
上面的代碼咱們咱們已經介紹了main.js如何轉爲RequireJS使用。如今咱們繼續討論其餘文件的定義。
purchase.js
define(["credits", "products"], function(credits, products) { console.log("Function : purchaseProduct"); return { purchaseProduct: function() { var credit = credits.getCredits(); if (credit > 0) { products.reserveProduct(); return true; } return false; } }; });
purchase須要調用getCredits()和reserveProduct(),因此必須加載credits.js和products.js文件
products.js
define(function(products) { return { reserveProduct: function() { console.log("function : reserveProduct"); return true; } }; });
credits.js
define(function() { return { getCredits: function() { console.log("Function : getCredits"); var credits = "100"; return credits; } }; });
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script data-main="scripts/main" src="scripts/require.js"></script> </head> <body> </body> </html>
上面的兩個文件被配置成獨立的模塊,意味着不依賴於其餘任何的東西。一樣的咱們發現咱們用的是define()而不是require()。有關require()和define()之間的選擇,咱們在下節中來討論。
require() VS define()
以前咱們提到能夠同時使用require()和define()來加載依賴關係。理解這兩個函數之間的差別對於管理依賴關係相當重要。require()用於運行即時功能,而define()用於定義多個位置的模塊。在main.js文件中咱們須要當即調用**purchaseProduct()**函數,因此咱們使用require,而其餘文件是可徵用的模塊,僅被其餘文件調用,因此咱們使用define()
RequireJS使用異步模塊加載(AMD)來加載文件。每一個依賴模塊經過給定的順序異步請求開始加載。儘管考慮了文件的順序,因爲 異步的特色,咱們沒法保證第一個文件會在第二個文件以前被加載。由於RequireJS須要經過shim配置來定義按正確的順序加載文件。咱們來看看RequireJS中如何建立配置選項。
requirejs.config({ shim: { source1: ["dependency1", "dependency2"], source2: ["source1"], backbone: { //backbone加載前須要加載的模塊 deps: ["underscore", "jquery"], exports: "Backbone"//暴露全局的名稱 }, 'jquery.scroll': { deps: ['jquery'], exports: 'jQuery.fn.scroll'//將scroll掛在jQuery的原型上 }, }, });
RequireJS容許咱們使用config()函數提供配置選項。按接收一個shim的參數,咱們來使用它來定義強制的依賴關係序列。
deps:表示當前模塊須要依賴哪些庫
exports:暴露的全局名稱
require.config({ urlArgs: "v=" + requirejs.s.contexts._.config.config.site.version, packages: [{ name: 'moment', location: '../libs/moment', main: 'moment' } ], //在打包壓縮時將會把include中的模塊合併到主文件中 include: ['css', 'layer', 'toastr', 'fast', 'backend', 'backend-init', 'table', 'form', 'dragsort', 'drag', 'drop', 'addtabs', 'selectpage'], paths: { 'lang': "empty:", 'form': 'require-form', 'table': 'require-table', 'upload': 'require-upload', 'validator': 'require-validator', 'drag': 'jquery.drag.min', 'drop': 'jquery.drop.min', 'echarts': 'echarts.min', 'echarts-theme': 'echarts-theme', 'adminlte': 'adminlte', 'bootstrap-table-commonsearch': 'bootstrap-table-commonsearch', 'bootstrap-table-template': 'bootstrap-table-template', // // 如下的包從bower的libs目錄加載 'jquery': '../libs/jquery/dist/jquery.min', 'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min', 'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min', 'bootstrap-daterangepicker': '../libs/bootstrap-daterangepicker/daterangepicker', 'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min', 'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN', 'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min', 'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min', 'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile', 'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN', 'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min', 'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort', 'sortable': '../libs/Sortable/Sortable.min', 'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs', 'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll', 'validator-core': '../libs/nice-validator/dist/jquery.validator', 'validator-lang': '../libs/nice-validator/dist/local/zh-CN', 'plupload': '../libs/plupload/js/plupload.min', 'toastr': '../libs/toastr/toastr', 'jstree': '../libs/jstree/dist/jstree.min', 'layer': '../libs/layer/dist/layer', 'cookie': '../libs/jquery.cookie/jquery.cookie', 'cxselect': '../libs/fastadmin-cxselect/js/jquery.cxselect', 'template': '../libs/art-template/dist/template-native', 'selectpage': '../libs/fastadmin-selectpage/selectpage', 'citypicker': '../libs/city-picker/dist/js/city-picker.min', 'citypicker-data': '../libs/city-picker/dist/js/city-picker.data', }, // shim依賴配置 shim: { 'addons': ['backend'], 'bootstrap': ['jquery'], 'bootstrap-table': { deps: [ 'bootstrap', // 'css!../libs/bootstrap-table/dist/bootstrap-table.min.css' ], exports: '$.fn.bootstrapTable' }, 'bootstrap-table-lang': { deps: ['bootstrap-table'], exports: '$.fn.bootstrapTable.defaults' }, 'bootstrap-table-export': { deps: ['bootstrap-table', 'tableexport'], exports: '$.fn.bootstrapTable.defaults' }, 'bootstrap-table-mobile': { deps: ['bootstrap-table'], exports: '$.fn.bootstrapTable.defaults' }, 'bootstrap-table-advancedsearch': { deps: ['bootstrap-table'], exports: '$.fn.bootstrapTable.defaults' }, 'bootstrap-table-commonsearch': { deps: ['bootstrap-table'], exports: '$.fn.bootstrapTable.defaults' }, 'bootstrap-table-template': { deps: ['bootstrap-table', 'template'], exports: '$.fn.bootstrapTable.defaults' }, 'tableexport': { deps: ['jquery'], exports: '$.fn.extend' }, 'slimscroll': { deps: ['jquery'], exports: '$.fn.extend' }, 'adminlte': { deps: ['bootstrap', 'slimscroll'], exports: '$.AdminLTE' }, 'bootstrap-datetimepicker': [ 'moment/locale/zh-cn', // 'css!../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css', ], 'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ], 'bootstrap-select-lang': ['bootstrap-select'], // 'toastr': ['css!../libs/toastr/toastr.min.css'], 'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ], 'plupload': { deps: ['../libs/plupload/js/moxie.min'], exports: "plupload" }, // 'layer': ['css!../libs/layer/dist/theme/default/layer.css'], // 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'], 'validator-lang': ['validator-core'], // 'selectpage': ['css!../libs/fastadmin-selectpage/selectpage.css'], 'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css'] }, baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //資源基礎路徑 map: { '*': { 'css': '../libs/require-css/css.min' } }, waitSeconds: 30, charset: 'utf-8' // 文件編碼 });