1. 认识
RequireJs 是一个 js 文件,用于 模块化的管理 js 文件,属于 AMD 规范的一种实现;可以 提升速度 和 提高代码质量;详情见官网:http://requirejs.org/
2. 使用
2.1 入口
配置 require.js 的 js 文件时,增加 data-main 属性,即为 js 的入口;
Note:data-main 所指定的 js 文件是 异步加载的,所以在页面指定多个 js 时,即便是放在 data-main 的下方也无法保证 加载的顺序;
对于入口文件的选择:
① 如果项目是将一个页面分为 多个 layout(tiles 布局,如 general:页面的整体,其他各个layout 填充该 页面;header:页面的头部,填充 genneral;footer:页面的尾部,填充 genneral;main:页面的主体,不同的页面分别创建,填充 general 等),可以在 genneral页面 引入配置文件;而在 main 页面 引入 各个页面的 js ;这样就可以保证 配置文件在 各个页面的 js 之前加载,就可以在 main 页面的 js 中 使用 配置文件中的配置;
② 如果并没有采用这种布局,那么不同 jsp 页面的 入口文件就使用 各个页面的 js 文件 ,如果要使用配置文件 定义新的模块,则可以在 define 引用的模块数组中加入 配置文件的js,然后加入配置文件中已配置的 js 名,在需要使用的时候,再使用 require 加载 配置文件中的 js 名,否则的话,无法引用到;示例如下:
定义公共util.js 模块 ,配置文件使用下方的 main.js
/**
* Created by xlch on 2016/12/27.
*/
//这里会使用到配置文件中配置的 jquery,所以依次引用 配置文件js,jquery
//这里虽然引用了 main 模块,但是其中只是声明了 jquery,要调用该模块仍然需要常规的 require 或者 define
//这里引用的 jquery 并不存在于js/lib/jquery 路径下,而是配置在 man.js 中,所以还需要下面的 require
define(['require','module','../main', 'jquery'],function (require,module) {
//这里才真正的加载到 jquery;而且 jquery 必须定义在 define 的模块数组中
var $ = require("jquery");
var utils = {};
utils.quick = {
click:function (method,node) {
var list = null;
if (node) {
list = $(node).find("[data-click]");
}else {
list = $("[data-click]");
}
list.on("click",function (eventObject) {
var click = $(this).data("click");
if (click && method[click]) {
return method[click].apply(this,[eventObject]);
}
});
},
offClick:function (method, node) {
if (node) {
$(node).find('[data-click]').off('click');
}else {
$('[data-click]').off('click');
}
}
};
return utils;
});
入口文件 栗子:
<script src="${ctx}/js/require.js" data-main="${ctx}/js/app/home"></script>
2.2 requirejs 配置文件
常用配置属性
baseUrl: 所有模块查找的根路径,
★ 如果未设置 baseUrl 参数,未使用 data-main 属性,则 baseUrl 的默认值 为 加载 require.js 的 HTML 页面 的 位置;
★ 如果未设置 baseUrl 参数,使用了 data-main 属性,那么 baseUrl 为 data-main 的 路径;
paths:在 baseUrl 下 不能直接发现的 模块名,则使用该选项映射路径,例如含有多级目录,或者在baseUrl 的上级目录;不需要 .js 后缀;
bundles:
shim:用于配置 不兼容的模块,即没有使用 define() 声明 依赖 并且 没有设置一个 模块名的 传统型 脚本;例如 backbone.js;
Note :shim配置仅设置了代码的依赖关系,想要实际加载shim指定的或涉及的模块,仍然需要一个常规的require/define调用。设置shim本身不会触发代码的加载。
其下有两个主要参数:
★ deps :用于声明依赖,数组的形式
★ exports:定义一个模块的名称,作为该 js 的全局引用
那些仅仅作为 jQuery 或者 Backbone 的插件存在,而不用导出任何模块变量的 模块,可以简单配置为依赖的数组;
requirejs.config({
shim: {
'jquery.colorize': ['jquery'],
'jquery.scroll': ['jquery'],
'backbone.layoutmanager': ['backbone']
}
});
waitSeconds:加载 js 等待的 最长时间,超时则放弃加载,默认时间为 7秒
配置文件栗子:
main.js:
/**
* Created by xlch on 2016/12/27.
*/
require.config({
//所有模块查找的根路径
baseUrl: 'js/lib',
//目的是将繁琐的引用名称简化,只需要 require(['jquery'],function(){})即可
//路径是相对于 baseUrl 的路径
paths: {
"jquery":'jquery/jquery-3.1.1.min',
},
// 配置非 amd 规范的 js ,增加依赖 和 输出名称
shim: { //
'backbone':{
depts:['jquery','underscore'],
exports:'Backbone'
},
'underscore':{
exports:'_'
},
},
//加载 js 等待的 最长时间,超时则放弃加载,默认时间为 7秒
waitSeconds: 30,
//main.js 之后加载的 js 的末尾添加后缀,防止缓存,但是生产环境需要去掉
// urlArgs: "bust=" + (new Date()).getTime(),
// 应用级别的参数,通过 module.config() 使用,未解
config:{
'name':{
na:'xlch'
},
},
});
2.3 define
define 用于定义一个 模块 ,定义的模块可以通过 require 调用;这里注意一定要将 结果返回,无论是对象还是函数; 因为 define 定义的模块是给 require 调用的;这样 define 就可以 被外部的其他 模块(module)捕捉到,即可以利用该模块;
例如上面定义一个公共的 util 模块,见上面的示例代码 util.js;
再copy 一下,使用上面的 main.js:
/**
* Created by xlch on 2016/12/27.
*/
//这里会使用到配置文件中配置的 jquery,所以依次引用 配置文件js,jquery
//这里虽然引用了 main 模块,但是其中只是声明了 jquery,要调用该模块仍然需要常规的 require 或者 define
//这里引用的 jquery 并不存在于js/lib/jquery 路径下,而是配置在 man.js 中,所以还需要下面的 require
define(['require','module','../main', 'jquery'],function (require,module) {
//这里才真正的加载到 jquery;而且 jquery 必须定义在 define 的模块数组中
var $ = require("jquery");
var utils = {};
utils.quick = {
click:function (method,node) {
var list = null;
if (node) {
list = $(node).find("[data-click]");
}else {
list = $("[data-click]");
}
list.on("click",function (eventObject) {
var click = $(this).data("click");
if (click && method[click]) {
return method[click].apply(this,[eventObject]);
}
});
},
offClick:function (method, node) {
if (node) {
$(node).find('[data-click]').off('click');
}else {
$('[data-click]').off('click');
}
}
};
return utils;
});
NOTE:无论是 define 还是 require,要想能够使用已知的模块,必须都要放在 其中的 模块名的数组([ ])中,无论是一级 require ,还是多级 require,他们都是在数组中;
2.4 require
require 用于调用 已定义的模块 完成页面渲染;与 define 的区别是,无返回值,不能够被外部其他的模块感知到;
示例代码:可以在用到某个 js 的时候再使用 require 加载;
/**
* Created by xlch on 2017/2/6.
*/
//加载配置文件js,以及默认提供的 module
require(['../main','module'],function (main,module) {
require(["../help/util"],function (util) {
util.quick.click({
delete:function () {
alert("delete");
}
});
require(['underscore'],function (_) {
var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
console.log(_.pluck(stooges, 'name'));
});
})
})
如果在加载配置文件的同时,还想使用 配置文件中配置的 module 的话,例如上面 main.js 中配置的 jquery:
可以这样:
require(['require', '../main', '../help/util'], function (require,main,util) {
util.quick.click({
delete: function () {
alert("delete 222");
}
});
require(['backbone'], function (Backbone) {
Backbone.Model.extend({});
});
require(['jquery'],function ($) {
console.log($("#h2").text());
})
})
但是如果我仿照 define 中那样使用 jquery 的话,会报错 ,jquery 404 not found
他寻找的地址为 js/app/jquery,但是我 main 中配置的 baseUrl 为 js/lib ,这里使用的路径是 js/app ;
按照推断,应该是此时的 main.js 还没有加载,不知道推断的是否正确
//这里会报错,无法找到 js/app/jquery.js ,而 jquery 的真正路径配置在 main.js 中
//说明,这里 main.js 应该还没有加载吗?按照上面的 baseUrl 产生规则
//设置了 data-main,未设置 baseUrl,则 baseUrl 为 data-main 的路径
//即 入口处贴的 js/app/home.js ,完全吻合;
require(['require', '../main', '../help/util', 'jquery'], function (require,main,util) {
var $ = require("jquery");
console.log($("#h2").text());
util.quick.click({
delete: function () {
alert("delete 222");
}
});
require(['backbone'], function (Backbone) {
Backbone.Model.extend({});
});
require(['jquery'],function ($) {
console.log($("#h2").text());
})
})
如果,这里我把 require 的 模块数组中的 jquery 去除,则可以成功跑通;如下代码调整
require(['require', '../main', '../help/util'], function (require,main,util) {
var $ = require("jquery");
console.log($("#h2").text());
util.quick.click({
delete: function () {
alert("delete 222");
}
});
require(['backbone'], function (Backbone) {
Backbone.Model.extend({});
});
require(['jquery'],function ($) {
console.log($("#h2").text());
})
})
另外,require 的模块数组 中提供了 domReady! ,作用是 保证 在 DOM 准备完毕之后 该 模块的函数 才能被调用;
require(['domReady!'], function (doc) {
//等待 DOM 加载完毕之后,调用该函数
});
为了防止加载时间过长,导致 requirejs 产生 超时的错误,可以在 配置文件 main.js 中 增加 waitSeconds 配置等待的最长时间,或者 使用 domReady() 方法调用;
require(['domReady'], function (dom) {
domReady(function () {
// DOM 加载完毕后执行
});
});
《 简单总结 ,未完待续 》