原文: https://www.tutorialspoint.com/requirejs/requirejs_quick_guide.htmjavascript
RequireJS是一个JavaScript库和文件加载器,用于管理JavaScript文件和模块化编程之间的依赖关系。它还有助于提升代码的速度和质量。css
RequireJS由David Mark开发,其初始版本v1.0.0于2009年发布。它是一个开源版本,2.3.3版本是其最近的稳定版本。html
它是MIT许可下的开源JavaScript库。java
它提供异步模块加载。node
它具备加载嵌套依赖项的能力。jquery
若是您有许多小文件,则无需担忧跟踪依赖关系顺序。git
它为插件提供支持并加载多个JavaScript文件。github
它管理JavaScript文件之间的依赖关系,并提升代码的速度和质量。ajax
它将模块组合并缩小为一个脚本,以优化体验。npm
它下降了大型应用程序中的代码复杂度
它在编译时从不一样的模块收集不一样的JavaScript文件。
它容许轻松调试,由于它从普通脚本标记加载文件。
在本章中,咱们将了解如何为RequireJS设置环境。为此,您须要下载最新版本的RequireJS库。您能够下载缩小版或详细版 。
下载后,咱们须要在您的libs文件夹中包含require.js文件,项目结构应以下所示 -
projectname/ |--index.html |--libs/ |---main.js |---require.js |---helper/ |----util.js
咱们须要将一个html文件定义为index.html ,其中加载了RequireJS,以下所示。
<html> <head> <script data-main = "libs/main" src = "libs/require.js"></script> </head> <body> <h1> RequireJS Sample Page </h1> </body> </html>
请注意,脚本标记中仅包含带有RequireJS调用的require.js以加载脚本。
有两种方法能够得到Node适配器。
npm - 您能够从命令提示符安装最新版本的requirejs,以下所示。
npm install requirejs
能够经过data-main属性传递HTML模板中的主要配置来初始化RequireJS。RequireJS使用它来知道在您的应用程序中加载哪一个模块。
例如 -
<scripts data-main = "scripts/main" src = "scripts/require.js"></script>
要包含Require.js文件,须要在html文件中添加脚本标记。在脚本标记内,添加data-main属性以加载模块。这能够做为您的应用程序的主要入口点。scripts / main是包含RequireJS配置的应用程序的主JavaScript文件。
如下是可在加载第一个应用程序模块时设置的配置选项 -
baseUrl - 它是经过RequireJS加载的全部模块的路由路径。 baseUrl由以“斜杠(/)”开头的字符串表示,包含协议并以“.js”扩展名结尾。若是没有指定baseUrl,则RequireJS使用data-main属性路径做为baseUrl。
paths - 它指定相对于baseUrl的模块的路径映射。在映射模块名称时,它会自动将.js扩展名添加到路径中。
shim - 它经过配置其依赖关系并导出其全局值,提供非AMD库与RequireJS的使用。
map - 对于给定的模块,应用程序经过共享其ID来为不一样的条件使用相同的代码,从而针对不一样的目标使用不一样版本的相同模块。
config - 它经过使用config选项为模块提供配置,这能够经过使用特殊依赖“模块”并调用其module.config()函数来完成。
urlArgs - 查询字符串参数用于获取使用RequireJS加载的全部资源。当浏览器或服务器配置不正确时,它用于缓存清除。
waitSeconds - 它指定在抛出脚本加载以前等待的秒数。默认值为“7”秒,“0”禁用超时。
packages - 它提供了用于配置加载模块的CommonJS包。
context - 它提供了上下文加载的名称,容许在页面中加载不一样的模块。
deps - 在加载RequireJS以前将Require指定为config对象时,它是一个依赖项数组。
回调 - 它在加载依赖项后执行一个函数,而且在加载RequireJS以前将Require指定为config对象时是必需的。
xhtml - 当此选项设置为true时,它用于经过使用document.createElementNS()方法建立脚本元素。
scriptType - 它定义文档中使用的脚本类型属性的值。默认类型是“text / javascript”。
skipDataMain - 若是此选项设置为true ,它会在加载模块时跳过data-main属性扫描 。
RequireJS中的模块是做用域对象,在全局命名空间中不可用。所以,全局命名空间不会受到污染。RequireJS语法容许更快地加载模块,而没必要担忧跟踪依赖项的顺序。您能够在同一页面中加载同一模块的多个版本。
模块使用define()函数定义 ;一样的功能也用于加载模块。
若是模块只是名称和值对的集合,那么您可使用如下语法 -
define({ state: "karnataka", city: "bangalore" });
模块也可使用函数,而不具备依赖性。这可使用如下语法来完成 -
define(function () { //Do setup work here return { state: "karnataka", city: "bangalore" } });
若是模块具备依赖关系,则第一个参数(依赖项名称数组),第二个参数(定义函数)和返回对象 以以下语法来定义一个模块 -
define(["./mnc", "./startup"], function(mnc, startup) { return { state: "karnataka", city: "bangalore", addCompany: function() { mnc.decrement(this); startup.add(this); } } } );
模块没必要仅返回对象,也能够返回函数中的任何有效值。如下语法用于将模块定义为函数 -
define(["./mnc", "./startup"], function(mnc, startup) { return function(title) { return title ? (window.title = title) : startup.storeName + ' ' + mnc.name; } } );
在某些状况下,您可能必须包含模块的名称做为define()的第一个参数。这能够经过使用如下语法来完成 -
define("js2/title", ["js1/mnc", "js1/startup"], function(mnc, startup) { //Define js2/title object in here. } );
define()函数可用于加载模块(模块能够是对象,函数,类或加载模块后执行的代码)。您能够在同一页面中加载同一模块的不一样版本。即便它们以不一样的顺序加载,也能够按相同的顺序分析不一样的版本。
define(['module1', 'module2'], function (module1, module2) { //define the module value by returning a value return function () {}; });
您能够在定义模块时传递模块名称列表,而且能够在执行模块以前使用RequireJS来检索这些模块。这些模块能够做为定义函数的参数进行传递。
如下示例显示了加载模块时define()函数的用法。建立一个名为index.html的html文件,并将如下代码放入其中 -
<!DOCTYPE html> <html> <head> <title>Define() Function</title> <script data-main = "main" src = "require.js"></script> </head> <body> <h2>RequireJS Define() Function Example</h2> </body> </html>
建立一个名为main.js的js文件,并在其中添加如下代码 -
define(function (require) { var myteam = require("./team"); var mylogger = require("./player"); alert("Player Name : " + myteam.player); mylogger.myfunc(); });
如今,再建立两个名为team.js和player.js的 js文件,并分别放置如下代码 -
define({ player: "Sachin Tendulkar", team : "India" });
define(function (require) { var myteam = require("./team"); return { myfunc: function () { document.write("Name: " + myteam.player + ", Country: " + myteam.team); } }; });
在浏览器中打开HTML文件;您将收到以下屏幕截图中的输出 -
单击“肯定”按钮,您将从模块中得到另外一个输出 -
在本章中,咱们将讨论RequireJS中的优化。 RequireJS中的优化器具备如下特征 -
将脚本文件与UglifyJS的帮助一块儿用于默认用法或Closure Compiler for Java用法
将CSS文件组合在一块儿。
优化器是Node和Nashorn的r.js适配器的一个组件。它被开发成为构建过程的一部分,而不是开发过程的一部分。
下载项目文件夹中的r.js后 ,文件夹的结构应以下所示 -
projectfolder/ |-->index.html |-->CSS/ |--->main.css |--->other.css |-->libs |--->require.js |--->main.js |--->dependent1.js |--->dependent2.js |--->dependent3.js
您的HTML文件将以下所示 -
<html> <head> <script data-main = "libs/main" src = "libs/require.js"></script> </head> <body> <h1> RequireJS Sample Page </h1> </body> </html>
你的main.js文件以下所示 -
require(["dependent1", "dependent2", "dependent3"], function (dependent1, dependent2, dependent3) { });
你的main.css文件以下所示 -
@import url("other.css"); .app { background: transparent url(../../img/app.png); }
您可使用命令行参数或配置文件构建属性来设置项目,二者均可以相互交换。
如下是命令行的语法 -
node r.js -o baseUrl = . paths.jquery = content/path/jquery name = main out = main-built.js
如下是构建配置文件的语法 -
({ baseUrl: ".", paths: { jquery: "content/path/jquery" }, name: "main", out: "main-built.js" })
在此以后,您能够在命令行中将构建配置文件名称传递给优化程序,以下所示 -
node r.js -o build.js
命令行参数语法有一些缺点。结合使用命令行参数或配置文件构建属性能够克服这些缺点。
要优化单个JS文件,您须要建立一个包含其全部依赖项内容的JS文件。您的文件应以下所示 -
({ baseUrl: "js/shop", paths: { "jquery": "jquery", "backbone": "backbone", "underscore": "underscore" }, shim: { "backbone": { "department": ["underscore", "jquery"], "dependent": "Backbone" }, "underscore": { exports: "_" } }, name: "../main", out: "../built/js/main.js" })
如今,您能够建立main.js文件,该文件具备app的全部依赖项。此文件在HTML文件中用于经过一个请求加载全部JS文件。注意,建立的文件不该该在源代码目录中;文件应该在项目的副本中。
优化程序不使用网络资源/ CDN(内容交付网络)加载脚本。若是须要使用CDN加载脚本,则须要将这些文件映射到模块名称并将文件下载到本地文件路径。您能够在构建配置文件的路径配置中使用特殊字“empty”,如如下语法所示 -
({ baseUrl: "js", name: "mainCDN", out: "js/mainCDN-built.js", paths: { jquery: "empty:" } })
主文件以下图所示 -
requirejs.config({ paths: { 'jquery': 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min' } }); require(['jquery'], function ($) { });
CSS文件直接在命令行中使用如下参数进行优化,以下所示 -
node ../../r.js -o cssIn = main.css out = main-built.css
CSS文件也可使用以下所示的相同属性在构建文件中进行优化 -
... cssIn:"main.css", out:"main-built.css" ...
上述两种方法都是容许的,并将建立一个名为projectfolder / css / mainbuild.css的文件。此文件将包含main.css的内容,正确调整的url()路径以及删除的注释。
优化程序使用构建配置文件来优化全部css和js文件。在如下示例中,将建立build.js文件。
({ baseUrl: "js/shop", appDir: '.', paths: { "jquery": "jquery", "backbone": "backbone", "underscore": "underscore" }, shim: { "backbone": { "deps": ["underscore", "jquery"], "exports": "Backbone" }, "underscore": { exports: "_" } }, optimizeCss: "standard.keepLines", modules: [ { name: "app" } ], dir: "../built" })
build.js文件指示RequireJS将全部应用程序文件夹(appDir参数)复制到构建的输出文件夹(dir参数),并将全部优化应用于位于输出文件夹中的文件。运行如下命令在app文件夹中构建配置文件 -
node r.js -o build.js
RequireJS使用jQuery做为另外一个依赖项并以小写形式注册为命名模块jquery ,默认状况下,在使用AMD / RequireJS时也使用全局函数$和jQuery注册自身。
require(['jquery'], function($) { //code here }
您能够加载多个自定义库以及jQuery,以下所示 -
require(['custom_library_path',jquery'], function(load_library,$) { //related code of $ and load_library });
下表显示了使用带有RequireJS的jQuery来指定它们的依赖关系。
Sr.No. | 类型和描述 |
---|---|
1 | 使用Shim Config jQuery使用shim配置来定义jQuery插件的依赖项。 |
2 | 从CDN加载jQuery jQuery使用CDN来定义jQuery插件的依赖项。 |
Node适配器能够与Require和Node的搜索路径一块儿使用。若是RequireJS没有使用模块配置,则可使用现有的基于节点的模块而无需更改它们。您可使用npm命令在项目的node_modules目录中安装节点包。
Node将仅从本地磁盘加载模块,而且只有在RequireJS加载模块时才会应用配置选项,例如map,packages,path等。
您可使用如下命令安装节点适配器,该命令将安装最新版本文件 -
npm install requirejs
您也能够经过如下方式安装节点 -
要使用该节点,您须要具备require('requirejs')并将配置中的require函数移动到顶级main.js文件。
例如 -
var requirejs = require('requirejs'); requirejs.config({ //load the mode modules to top level JS file //by passing the top level main.js require function to requirejs nodeRequire: require }); requirejs(['name1', 'name2'], function (name1, name2) { //by using requirejs config, name1 and name2 are loaded //node's require loads the module, if they did not find these } );
您可使代码模块与RequireJS和Node一块儿使用,而无需库的用户,而后使用amdefine包来完成此工做。
例如 -
if (typeof define !== 'function') { var define = require('amdefine')(module); } define(function(require) { var myval = require('dependency'); //The returned value from the function can be used //as module which is visible to Node. return function () {}; });
节点模块使用RequireJS优化器做为优化方法,使用函数调用而不是使用命令行工具。
例如 -
var requirejs = require('requirejs'); var config = { baseUrl: '../directory/scripts', name: 'main', out: '../build/main-built.js' }; requirejs.optimize(config, function (buildResponse) { //The text output of the modules specify by using buildResponse //and loads the built file for the contents //get the optimized file contents by using config.out var contents = fs.readFileSync(config.out, 'utf8'); }, function(err) { //code for optimization err callback });
Dojo是一个基于AMD模块体系结构的JavaScript工具包,它提供了额外的模块来为Web应用程序添加额外的功能,还节省了Web应用程序开发过程当中的时间和规模。
如下示例显示了Dojo和RequireJS的用法。建立一个名为index.html的html文件,并将如下代码放入其中 -
<!DOCTYPE html> <html> <head> <title>RequireJS Dojo</title> <script data-main="app" src="lib/require.js"></script> </head> <body> <h2>RequireJS Dojo</h2> <p> Hello... ... </p> </body> </html>
建立一个名为app.js的js文件,并在其中添加如下代码 -
require ({ //You can configure loading modules from the lib directory baseUrl: 'lib', paths: { //mapping of package dojo: 'http://sfoster.dojotoolkit.org/dojobox/1.7-branch/dojo' } }, [ //modules which we are using here 'dojo/dom' ], function(dom) { //using the 'byId' method from dom module var mydojo = dom.byId('dojo_val') mydojo.innerHTML = "The text is displaying via dojo/dom"; } );
在浏览器中打开HTML文件;您将收到如下输出 -
模块格式由CommonJS定义。它的定义没有为其余JavaScript环境提供相同的浏览器选项。所以,CommonJS规范推荐传输格式和异步需求 。您能够轻松转换传统的CommonJS模块格式以使用RequireJS。可是,全部模块都不会转换为新格式。下面列出了一些例外状况 -
可使用如下语法将CommonJS模块手动转换为RequireJS格式 -
define(function(require, exports, module) { //place CommonJS module content here });
可使用r.js项目转换器工具将CommonJS模块转换为RequireJS格式,该工具内置于r.js文件中。您应该指定要转换的文件的路径和输出文件夹,以下所示 -
node r.js -convert path/to/commonjs/modules/ path/to/output
CommonJS中的一些系统容许经过将导出值指定为module.exports来设置导出值。但RequireJS支持从传递给define的函数返回值的更简单方法。这样作的好处是你不须要export和module函数参数,因此你能够将它们从模块定义中删除,以下所示 -
define(function (require) { var name = require('name'); //Define the module as exporting a function return function () { name.doSomething(); }; });
指定依赖关系的另外一种方法是经过依赖数组参数define() 。可是,依赖项数组中的名称顺序应该与传递给定义函数define()的参数顺序相匹配,以下所示 -
define(['name'], function (name) { return function () { name.doSomething(); }; });
要了解位置和包属性,能够经过设置RequireJS配置使用RequireJS在CommonJS包中加载模块。
RequireJS中提供了优化工具,能够将模块定义组合到优化的浏览器交付包中。它做为命令行工具运行,所以您能够将其用做代码部署的一部分。
RequireJS包含一小组插件,容许将各类类型的资源做为依赖项加载。如下是RequireJS中可用插件的列表 -
文本插件用于异步加载基于文本的资源,主要用于在JavaScript文件中插入HTML内容。它能够在您使用文本时加载! 任何require或define模块调用中的前缀,并将文件扩展名传递给插件。与普通模块加载相比, 文本插件使用XHR加载模块,而且不会将代码做为脚本标记添加到标头中。
文本文件资源能够做为依赖项包含在代码中 -
require(["mymodule", "text!mymodule.html", "text!mymodule.css"], function(mymodule, html, css) { //the html and css variables will be the text //of the mymodule.html file and mymodule.css files respectively } );
RequireJS可用于在DOM准备好以前加载脚本,开发人员只有在脚本彻底加载时才能与DOM交互。有时能够在DOM准备好以前加载脚本。所以,为了克服这个问题,RequireJS提供了称为DOMContentLoaded事件的现代方法,一旦DOM准备好就会调用domReady函数。
require(['domReady'], function(domReady) { domReady(function() { //the domReady function is called when DOM is ready //which is safe to manipulate DOM nodes in this function }); });
它能够与提供i18n bundle支持的多个语言环境一块儿使用,当模块或依赖项指定“i18n!”时,它将自动加载。“ 字首。要使用它,请下载它并将其放在存在主JavaScript文件的同一目录中。将此插件放在名为“nls”的目录中以查找本地化文件。
例如,假设咱们有一个名为country.js的 js文件,其中包含如下内容,并将其做为mydirectory / nls / country.js放在目录中 -
define({ "root": { "india": "india", "australia": "australia", "england": "england" } });
您可使用fr-fr语言环境向文件添加特定的翻译,上面的代码将更改成 -
define({ "root": { "title": "title", "header": "header", "description": "description" }, "es-es": true });
接下来,使用如下内容在mydirectory / nls / es-es / country.js中指定文件 -
define({ "root": { "title": "título", "header": "cabecera", "description": "descripción" }, "es-es": true });
您能够经过main.js文件中模块配置的帮助将其传递给插件来设置语言环境,以下所示 -
requirejs.config({ config: { //set the config for the i18n plugin i18n: { locale: 'es-es' } } });
您可使用一些插件加载CSS文件,只需附加到标题连接便可加载CSS文件。
可使用您本身的函数加载CSS,以下所示 -
function myCss(url) { var mylink = document.createElement("mylink"); mylink.type = "text/css"; mylink.rel = "stylesheet"; mylink.href = url; document.getElementsByTagName("head")[0].appendChild(mylink); }