Awesome
RequireJS
require.js加载js文件的好处
- 可以防止JS加载时候阻塞页面渲染(JS运行时候DOM停止渲染的情况)
- 使用require.js调用的方式加载JS,不用在像以前那样多个
<script>
标签引入JS文件
所有代码的目录结构如图
传统的引入
start.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/a.js"></script>
</head>
<body>
<p>wsscat</p>
</body>
</html>
传统方法引入可以看到会先弹出alert,内容被阻塞没有渲染
a.js
function cat() {
alert("hello");
}
cat();
require.js的引入
start.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js/require.js"></script>
<script>
require(["js/a"]);
</script>
</head>
<body>
<p>wsscat</p>
</body>
</html>
a.js
define(function () {
function cat() {
alert("hello");
}
cat();
})
现在应require里面写可以避免以前的写法导致alert弹窗时候页面的p
标签内容被阻塞无法渲染
现在这种写法格式是用define定义一个模块,并在页面中调用require方法引入
要注意的是,require接受的是一个数组,它注入的依赖是一个数组,哪怕数组只有一个依赖,而它第二个参数则可以传入一个回调函数,就是党数组中的依赖都加载完毕后,执行这个回调函数,比如我们可以加载jQuery的依赖,然后再回调函数中调用jQuery的库
require(["js/a"]);
config方法
我们可以在上面代码上继续改进,可以用require.js的config方法,通过paths属性,就不用每次都写这么长的引入地址,有点像angular的服务注册,然后在控制器中注入相应的服务
base.js
require.config({
paths: {
"jq": ["http://wsa.wsscat.com/jquery", "js/jquery"],
"a": "js/wsscat"
}
})
注意加载模块时不用写.js后缀,写了会报错 我们可以把配置这样引入到主页里面
<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/base.js"></script>
##path属性 用paths还有一个好处就是让我们配置多个路径去加载js,当我们请求第一个路径不成功时候,可以继续往后面请求第二个js路径代替
##data-main
我们还可以这样引入,在require引入的script标签中加入data-main属性,后面就不用在显式用<script>
标签引入其他脚本文件了
<script type="text/javascript" data-main="js/base" src="js/require.js"></script>
base.js
require.config({
baseUrl: 'js',
paths: {
jq: ["http://wsa.wsscat.com/jquery", "jquery"],
a: "wsscat"
}
})
require(["jq", "a"], function () {
$('span').css('color', '#673AB7');
});
可以看到已经成功加载到我们所需要的依赖了
RequireJS的模块语法允许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的,就是说模块是异步不按顺序加载,但使用的时候只要依赖的顺序正确那就会按依赖摆放的顺序执行
上面我们可以把之前的代码改进成这样,用define采用AMD规范,把方法写进模块里面,并以对象传递出来 wsscat.js
define(
function () {
function fun1() {
alert("wsscat");
}
function fun2() {
alert("autumns");
}
return {
f1: fun1,
f2: fun2
}
}
)
base.js
require.config({
baseUrl: 'js',
paths: {
jquery: ["http://wsa.wsscat.com/jquery", "jquery"],
a: "wsscat"
},
})
require(["jquery", "a"], function ($, a) {
console.log($('span'));
$('span').css('color', '#673AB7');
console.log(a);
});
然后注入a的JS,并依赖此服务,是输出a,就能看到我们刚才模块给的对象里面的两个函数
模块依赖另一个模块
如果我们在一个依赖中还要再去依赖另一个JS,理解来相当于angular在服务中还需要注入其他服务来扩展 我们就可以继续这样改,在define中加入一个数组,让我们想把需要的依赖给填充进去,记得回调函数里面需要把这个依赖也加进去形参里面 wsscat.js
define(['wsscat2'],
function (wsscat2) {
function fun1() {
alert("wsscat");
}
function fun2() {
alert("autumns");
}
return {
f1: fun1,
f2: fun2,
f3: wsscat2.f1
}
}
)
wsscat2.js
define(
function () {
function fun1() {
return "wsscat2.js's wsscat";
}
function fun2() {
return "wsscat2.js's autumns";
}
return {
f1: fun1,
f2: fun2
}
}
)
上面我们就完成了wsscat这个模块依赖了wsscat2模块,然后再次输出新的对象方法
shim(非AMD写法的兼容)导入单个变量
当我们遇到非AMD兼容写法的时候,我们要可以用exports方法,注意的是export方法只能输出一个方法或者对象 base.js
require.config({
//可以把下面共同指向js文件夹写在这个位置
baseUrl: 'js',
//path可以让我省略冗长的地址信息
paths: {
//可以配置多个路径,当js请求不成功,可以有备选路径
jquery: ["http://wsa.wsscat.com/jquery", "jquery"],
//define中再依赖其他模块
a: "wsscat",
//define遵从AMD的写法
b: "wsscat2",
//export一个对象
c: "wsscat3",
//export一个函数
d: "wsscat4"
},
//非AMD规范时候的兼容写法
//export暴露出对应的对象和方法
shim: {
c: {
//导出对象
exports: "obj",
},
d: {
//导出方法
exports: "fun4"
}
}
})
//注入对应依赖,当依赖都请求成功后执行对应的回调函数
require(["jquery", "a", "c", "d"], function ($, a, c, d) {
console.log($('span'));
$('span').css('color', '#673AB7');
console.log(a.f3());
console.log(c);
console.log(d);
});
wsscat3.js
function fun1() {
return "wsscat3.js's wsscat";
}
function fun2() {
return "wsscat3.js's autumns";
}
var obj = {
f1: fun1,
f2: fun2
}
wsscat4
function fun4() {
return "wsscat4.js's wsscat";
}
上面我们就可以用exports方法分别把wsscats3和wsscat4里面的对象和方法暴露出来了
init(非AMD写法的兼容)导入多个变量
e: {
init: function() {
return {
fun5: fun5,
fun6: fun6
}
}
}
我们可以用init方法来导入多个变量,比shim属性导入单个零活,注意return里面的属性值是没有双引号的
require/text
我们利用text插件为组件引入html和css
使用npm下载require/text
模块或者在github中下载text.js文件
npm install requirejs/text
然后在配置文件
require.config({
baseUrl: 'js',
paths: {
text: ["text"],//<-添加这一个模块
jquery: ["jquery"],
bsheader: "../extends/bsheader/bsheader",
bsmain: "../extends/bsmain/bsmain",
bsfooter: "../extends/bsfooter/bsfooter",
bsmodal: "../extends/bsmodal/bsmodal"
}
})
//并注入对应依赖,当依赖都请求成功后执行对应的回调函数
require(["jquery", "text", "bsheader", "bsmain", "bsfooter"], function ($, text, bsheader, bsmain, bsfooter) {
console.log(text);
$("bsheader").bsheader();
$("bsmain").bsmain();
$("bsfooter").bsfooter();
});
然后我们就可以在组件中这样引入css和html文件了,注意要先插入html到页面再绑定事件,不然事件会失效,并且引入html和css文件时候要记得这样引入text!./bsfooter.html
text!加上文件路径的名字
define(["jquery", "text!./bsfooter.html", "text!./bsfooter.css"],
function ($, html) {
var html = html;
return $.fn.extend({
bsfooter: function (option) {
return this.each(function () {
$(this).html(html);
});
}
});
}
)