1.require下载和加载
1.1 下载
工欲善其事必先利其器,先下载require.js下载地址, 然后添加 require.js 到 scripts 目录
1.2 加载
然后加载require
<script data-main="js/app" src="js/require.js"></script>
data-main属性的作用是,指定网页程序的主模块
注意,这里写的是app而不是app.js。RequireJS默认假定所有的依赖资源都是js脚本,因此无需在module ID上再加".js"后缀,RequireJS在进行module ID到path的解析时会自动补上后缀.
1.3 baseUrl、path配置
在上面的app.js里的模块代码有
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){ // some code here });
默认情况'jquery', 'underscore', 'backbone'是和app.js在同一目录下。如果这些文件不和app.js在同一目录怎么办,比如js/lib目录下。
两种办法:
第一种办法:改变paths
require.config({ paths: { "jquery": "lib/jquery.min", "underscore": "lib/underscore.min", "backbone": "lib/backbone.min" } });
第二种办法:改变baseurl
baseUrl :所有模块的查找根路径。如未显式设置baseUrl,则默认值是加载require.js的HTML所处的位置。如果用了data-main属性,则该路径就变成baseUrl。
require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", "underscore": "underscore.min", "backbone": "backbone.min" } });
1.4加载非规范的模块
有些模块并不是规范的AMD,如果已存在的jquery等控件。这样的文件如果 加载
require.config({ shim: { 'jquery':{ exports: $' }, 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } });
2.定义模块
一个磁盘文件应该只定义 1 个模块。多个模块可以使用内置优化工具将其组织打包。
2.1简单的值对
define({ color: "black", size: "unisize" });
2.2函数式定义
如果一个模块没有任何依赖,但需要一个做setup工作的函数,则在define()中定义该函数,并将其传给define():
define(function () { //Do setup work here return { color: "black", size: "unisize" } });
2.3存在依赖的函数式定义
第一个参数是依赖的名称数组;第二个参数是函数,在模块的所有依赖加载完毕后,该函数会被调用来定义该模块,因此该模块应该返回一个定义了本模块的object。
define(["./cart", "./inventory"], function(cart, inventory) { //return an object to define the "my/shirt" module. return { color: "blue", size: "large", addToCart: function() { inventory.decrement(this); cart.add(this); } } } );
2.4定义一个命名模块
//Explicitly defines the "foo/title" module: define("foo/title", ["my/cart", "my/inventory"], function(cart, inventory) { //Define foo/title object in here. } );
显式指定模块名称,但这使模块更不具备移植性
2.5循环依赖
如果你定义了一个循环依赖(a依赖b,b同时依赖a),则在这种情形下当b的模块函数被调用的时候,它会得到一个undefined的a.解决办法
//Inside b.js: define(function(require, exports, module) { //If "a" has used exports, then we have a real //object reference here. However, we cannot use //any of a's properties until after b returns a value. var a = require("a"); exports.foo = function () { return a.bar(); }; });
2.6 两类模块需要使用不同版本的"foo"
该手段对于某些大型项目很重要:如有两类模块需要使用不同版本的"foo",但它们之间仍需要一定的协同
map示例:
requirejs.config({ map: { 'some/newmodule': { 'foo': 'foo1.2' }, 'some/oldmodule': { 'foo': 'foo1.0' } } });
如果各模块在磁盘上分布如下:
- foo1.0.js
- foo1.2.js
- some/
- newmodule.js
- oldmodule.js
当“some/newmodule”调用了“require('foo')”,它将获取到foo1.2.js文件;而当“some/oldmod
requirejs.config({ config: { 'bar': { size: 'large' }, 'baz': { color: 'blue' } } }); //bar.js, which uses simplified CJS wrapping: //http://requirejs.org/docs/whyamd.html#sugar define(function (require, exports, module) { //Will be the value 'large' var size = module.config().size; }); //baz.js which uses a dependency array, //it asks for the special module ID, 'module': //https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#wiki-magic define(['module'], function (module) { //Will be the value 'blue' var color = module.config().color; });
若要将config传给包,将目标设置为包的主模块而不是包ID:
ule”调用“`require('foo')”时它将获取到foo1.0.js。
2.7配置信息
config:常常需要将配置信息传给一个模块,并调用module.config()。
requirejs.config({ //Pass an API key for use in the pixie package's //main module. config: { 'pixie/index': { apiKey: 'XJKDLNS' } }, //Set up config for the "pixie" package, whose main //module is the index.js file in the pixie folder. packages: [ { name: 'pixie', main: 'index' } ] });
一个常见的应用场景是先用库的一个CDN版本,如果其加载出错,则切换到本地版本:
requirejs.config({ enforceDefine: true, paths: { jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min' } }); //Later require(['jquery'], function ($) { //Do something with $ here }, function (err) { //The errback, error callback //The error has a list of modules that failed var failedId = err.requireModules && err.requireModules[0]; if (failedId === 'jquery') { //undef is function only on the global requirejs object. //Use it to clear internal knowledge of jQuery. Any modules //that were dependent on jQuery and in the middle of loading //will not be loaded yet, they will wait until a valid jQuery //does load. requirejs.undef(failedId); //Set the path to jQuery to local path requirejs.config({ paths: { jquery: 'local/jquery' } }); //Try again. Note that the above require callback //with the "Do something with $ here" comment will //be called if this new attempt to load jQuery succeeds. require(['jquery'], function () {}); } else { //Some other error. Maybe show message to the user. } });
注意: errback仅适用于回调风格的require调用,而不是define()调用。define()仅用于声明模块。
更简单办法
requirejs.config({ //To get timely, correct error triggers in IE, force a define/shim exports check. enforceDefine: true, paths: { jquery: [ 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min', //If the CDN location fails, load from this location 'lib/jquery' ] } }); //Later require(['jquery'], function ($) { });
全局 requirejs.onError
requirejs.onError = function (err) { console.log(err.requireType); if (err.requireType === 'timeout') { console.log('modules: ' + err.requireModules); } throw err; };
页面加载事件及DOM Ready
domReady模块实现了一个跨浏览器的方法来判定何时DOM已经ready。下载并在你的项目中如此用它:
require(['domready!'], function (doc){ // called once the DOM is ready });