源码地址: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' // 文件编码 });