requirejs是种比较流行的框架 ,因为前期一直未有时间整理下,今天正好工作不太忙,决定整理下:
在简单的网页实现中,我们常常通过<scripttype="text/javascript"src="firsttest.js"></script>的方式将js文件导入,但是这种导入随着网页的复杂程度的提高,已经不能满足现在互联网开发模式。
问题描述:
加载js会堵塞浏览器浏览器渲染
例如:
index.html
<!DOCTYPE html>
<html>
<head>
<scripttype="text/javascript"src="firsttest.js"></script>
</head>
<body>
<span>hello world</span>
</body></html>
firsttest.js:
(function(){
function fun1()
{alert("nihao");
}
fun1();})()
我们注意到alert执行的时候,html内容是一片空白的,即<span>hello world</span>
并未被显示,当点击确定后,才出现,这就是JS阻塞浏览器渲染导致的结果。于是有了AMD的概念
(AMD)
Asynchronous Module Definition,用白话文讲就是 异步模块定义,对于 JSer 来说,异步是再也熟悉不过的词了,所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中。
上述两个问题,有了requirejs使得问题解决,当然requirejs的好处还不止如此
下面详细描述如何使用requirejs:
常用API:require .define(
define 是用来定义一个模块
require加载依赖模块,执行加载模块后有回调函数
)因为在最近的web项目中有用到这个,所以在这篇文章中,以工作中应用为主
web项目首页index.html
在index.html中
首先加载requirejs文件
<script src="js/require.js" defer async="true" ></script>
defer async="true"指的是异步加载,defer因为只有IE支持
然后<script src='js/require.js' data-main='js/main'></script>
data-main作用是指定网页程序的主模块,requirejs加载的文件后缀名为js,所以此处的main指的是main.js
主模块写法
main.js是主模块,整个index.html的主页面
如果我们的主模块不依赖任何模块,则直接写入
//main.js
console.log('main.js未依赖于其他模块');
alert('success');
但是此时因为没有依赖于其他模块,所以不需要用到require
但是通常情况下是有依赖
require(['firstmodule,secondmodule,thirdmodule'],function(firist,second,third){
//your code here
});
require()函数需要两个参数,第一个参数为数组,不管只是依赖于一个模块后多个模块,都统一用数组,上文指的是主模块依赖于这三个模块,第二个参数是回调函数,指的是当这三个模块都加载成功后,后面的这个函数都会被调用。加载的模块以参数形式传入该函数,从而在回调中使用这些模块,因为是回调函数,则前面的模块都加载完成后才会运行,解决了依赖问题
模块的加载
上个模块举的例子,对依赖模块没有自定义,常常现实情况是依赖模块可能与main.js并不在一个文件夹下或者存在不同版本问题,所以针对这个问题,使用require.config)方法,我们对模块的加载行为进行自定义。require.js写下main.js的头部,参数就是一个对象,这个对象的paths属性指定各个模块的加载路径
require.config(
paths:{
'jquery':'a/jquery.min',
'backbone':'a/backbone.min'
}
);
这种情况对于每一个依赖库都需要修改路径,我们可以用另一种方法即直接改变基本目录(baseUrl)
require.config(
baseUrl:'js/a',
paths:{
'jquery':'jquery.min',
'backbone':'backbone.min'
}
);
当模块不在自己的主机上时候,我们可以指定它的网址
require.config({
path:{
'backbone':'www.baidu.com/js/backbone.js'
}
});
require.js要求,每个模块是一个单独的js技术,这样的话,如果加载多个模块,就会发出多次http请求,会影响网页的加载速度,因此require.js提供了优化
工具(http://requirejs.org/docs/optimization.html)???????,当模块部署完毕后,可以用这个工具将多个模块合并为一个文件中,减少HTTP请求
AMD模块的写法
所谓amd规范指的是异步加载,具体来说,模块本身必须采用define()函数来定义,如果一个模块不依赖于其他模块,则直接定义在
define()函数中
假定现在有一个secondtest.js文件,它定义了一个secondtest模块。那么,secondtest.js就要这样写:
sescondtest.js
define(function(){
var add=function(x,y){
return x+y;
};
return {
add:add
};
});
加载方法:
main.js
require(['secondtest'],function(second){
alert(secondtest.add(1,1));
});
如果这个模块依赖于其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性
define(['myLib'],function(myLib){
function foo(){
myLib.doSomething();
}
return {
foo : foo
};
});
加载非规范模块
理论上,requirejs加载模块,必须是按照AMD规范,用define函数定义的模块,但是遗憾的是很多现在流行的js并不是符合AMD规范,那么requirejs在加载非规范的模块时需要做处理
这样的模块在用require1加载前,要先用requre.config()定义一些特性
require.config({
shim:{
"underscore": {
"exports": "_"
},
"handlebars" : {
"deps" : ["jquery"],
"exports" : "Handlebars"
}
}
});
require.config()接受一个配置对象,这个对象除了前面说过的paths属性外,还有一个shim属性,专门用了配置不兼容的模块,exports定义的是输出的变量名,可以用简称,表明这个模块外部调用的名称deps数组,表明该模块的依赖性
比如,jQuery插件可以这样定义:
shim:{
'jquery.scroll':{
deps:['jquery'],
exports:'jquery.fn.scroll'
}
}
require.js插件
text和image插件,则是允许require.js加载文本和图片文件。
define([
'text!review.txt',
'image!cat.jpg'
],
function(review,cat){
console.log(review);
document.body.appendChild(cat);
}
);
自己工作中的应用:require.config({
waitSeconds: 0,
baseUrl: '../default/',
paths: {
// Core Libraries
"jquery": "framework/lib/jquery-1.9.1.min",
"underscore" : "framework/lib/underscore",
"backbone" : "framework/lib/backbone",
"handlebars" : "framework/lib/handlebars-v1.3.0",
"tinypubsub" : "framework/lib/ba-tiny-pubsub.min",
"swipeview": "framework/lib/swipeview",
"iscroll5": "framework/lib/iscroll-zoom",
"text" : "framework/lib/requirePlugin/text",
"css" : "framework/lib/requirePlugin/css",
"json" : "framework/lib/requirePlugin/json",
"_fetchText": "framework/lib/requirePlugin/_fetchText",
"chineseTopinyin" : "framework/lib/jQuery.Hz2Py-min",
},
shim: {
"backbone": {
"deps": [ "underscore"],
"exports": "Backbone"
},
"underscore": {
"exports": "_"
},
"handlebars" : {
"deps" : ["jquery"],
"exports" : "Handlebars"
},
}
});
写的比较仓促,欢迎大家指正(注:有部分参考http://www.ruanyifeng.com/blog/2012/11/require_js.html)