使用了块作用域来申明function防止污染全局变量 声明不同js文件之间的依赖 可以按需、并行、延时载入js库 可以让我们的代码以模块化的方式组织
通常使用requirejs的话,我们只需要导入requirejs即可,不需要显式导入其它的js库,因为这个工作会交给requirejs来做。
requirejs下。其主要API主要是下面三个函数:
require.config配置参数选项
requirejs一共提供了两个全局变量:
另外还可以把
依赖一个不使用requirejs方式的库
如果没用
先看下面不能正确工作的代码:
这段代码会报错,提示: Uncaught TypeError: undefinedisnot a function
在这种情况下,我们要使用
再运行就正常了。
上面代码
所以:
暴露多个变量:init
如果我要同时暴露多个全局变量呢?比如,
它定义了两个函数,而我两个都想要。这时就不能再用
当 无主的与有主的模块
为什么我只能使用
它会提示我:jqisundefined 但我仅仅改个名字:
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"], /// 这样配置后,当百度的jquery没有加载成功后,会加载本地js目录下的jquery}});requirejs(['jquery'], function(jq) { alert(jq);});
就一切正常了,能打印出 有主的模块经常研究,发现原来在jquery中已经定义了:
它这里的 所以当我们使用另一个名字:
去引用这个库的时候,它会发现,在 所以我们在使用一个第三方的时候,一定要注意它是否声明了一个确定的模块名。 无主的模块如果我们不指明模块名,就像这样:
那么它就是无主的模块。我们可以在 为什么有的有主,有的无主可以看到,无主的模块使用起来非常自由,为什么某些库(jquery, underscore)要把自己声明为有主的呢?
按某些说法,这么做是出于性能的考虑。因为像 而把它们声明为有主的,那么所有的模块只能使用同一个名字引用它们,这样系统就只会载入它们一次。 挖墙角
对于有主的模块,我们还有一种方式可以挖墙角:不把它们当作满足requirejs规范的模块,而当作普通js库,然后在
这样通过暴露 不过我们完全没有必要这么挖墙角,因为对于我们来说,似乎没有任何好处。 如何完全不让jquery污染全局的$
在前面引用jquery的这几种方式中,我们虽然可以以模块的方式拿到jquery模块的引用,但是还是可以在任何地方使用全局变量 在init中调用noConflict (无效)首先尝试一种最简单但是不工作的方式:
这样是不工作的,还是会弹出来一个非
使用另一个名字如果我们使用挖墙角的方式来使用jquery,如下:
这样的确有效,这时弹出来的就是一个
我们要么得手动修改第三方模块的代码,要么再为它们提供一个 但是如果我不使用shim这个参数的话,在最新版的requirejs2.1.15中(以前的版本我不太清楚),也可以通过require([‘XX’])来解决。 使用map
如果我们有办法能让在继续使用 我们可以再定义一个模块,仅仅为了执行这句代码: jquery-private.js
然后在入口处先调用它:
这样的确可行,但是还是会有问题: 我们必须小心的确保
我们这时可以引入
这样做,就解决了前面的问题:在除了jquery-private之外的任何依赖中,还可以直接使用 Map参数: Map参数是用来解决同一个模块不同版本的问题,比如在项目开发中,开发初期使用了jquery1.7版本,但是由于业务的需求需要引入jquery1.9以上的版本时候,但是又担心有些是依赖于jquery1.7的代码升级到1.9以上的时候会有问题,因此可以让一部分代码还是依赖于jquery1.7,薪增的代码依赖于jquery1.9.
现在我在入口文件app.js添加如下代码: requirejs.config({ map: { 'app/a': { 'jquery': 'js/lib/jquery1.7.js' }, 'app/b': { 'jquery': 'js/lib/jquery1.9.1.js' } } }); require(['app/a'],function(jq){ }); require(['app/b'],function(jq){ }); 然后在app/a.js添加如下代码: // a.js define(function (require, exports, module) { var a = require(['jquery']); }); 在app/b.js添加如下代码: // b.js define(function (require, exports, module) { var b = require(['jquery']); }); 在app.js中 require(['app/a'],function(jq){ });时候,在加载app/a.js的时候会加载jquery1.7.js文件,在加载app/b.js的时候会加载jquery1.9.1.js.如下截图所示:
如果在app.js中把下面这行b.js代码初始化注释掉 require(['app/b'],function(jq){ }); 那么就只会加载app/a.js及对应的jquery1.7.js,截图如下:
相应的 如果把app/a.js初始化代码注释掉,把app/b.js代码初始化打开,那么只会加载jquery1.9.1,可以看到如果我想app/b.js中使用jquery1.9的话,那么可以这样使用了。 config参数: config是指需要将配置信息传给一个模块,这些配置往往是application级别的信息,需要一个手段将他们向下传递给模块。在requireJS中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块可以加载特殊的依赖 ”moudle” ,并调用module.config(). 首先我们可以还是试着做demo来理解下上面话的意思吧,我现在在项目requirejs下js/app文件下新建一个d.js. 然后在app.js初始化文件加入如下代码: requirejs.config({ config: { 'app/c': { size: 'large' }, 'app/d': { color: 'blue' } } }); require(['app/c'],function(c){ console.log(c); }); require(['app/d'],function(dss){ console.log(d); }); 在c.js里面这样写代码: define(function (require, exports, module) { //其值是'large' var size = module.config().size; return size; }); 在控制台下运行可以看到能打印出 large值出来,这说明我们可以通过config配置项来给app/c.js传递一个模块信息,比如如上面的一个对象{size:large},而在c.js里面直接可以通过module.config()方法来获取size的值。 下面我们可以使用一个依赖数组来做同样的事情,如下d.js代码: define(['module'], function (module) { //Will be the value 'blue' var color = module.config().color; return color; }); 在控制台看 也一样可以打印出color值出来。
如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。 假定现在有一个math.js文件,它定义了一个math模块。那么,math.js就要这样写:
加载方法如下:
jQuery的插件可以这样定义:
require.js还提供一系列插件,实现一些特定的功能。 domready插件,可以让回调函数在页面DOM结构加载完成后再运行。
text和image插件,则是允许require.js加载文本和图片文件。
类似的插件还有json和mdown,用于加载json文件和markdown文件。
require.config({ shim: { "underscore" : { exports : "_"; }, "jquery.form" : { deps : ["jquery"] } } })
也可以简写为: require.config({ shim: { "underscore" : { exports : "_"; }, "jquery.form" : ["jquery"] } }) 这样配置之后我们就可以使用加载插件后的jquery了 require.config(["jquery", "jquery.form"], function($){ $(function(){ $("#form").ajaxSubmit({...}); }) })
define 从名字就可以看出这个api是用来定义一个模块 require 加载依赖模块,并执行加载完后的回调函数(注意require中的依赖是一个数组,即使只有一个依赖,你也必须使用数组来定义) paths还有一个重要的功能,就是可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库 之前的例子中加载模块都是本地js,但是大部分情况下网页需要加载的JS可能来自本地服务器、其他网站或CDN,这样就不能通过这种方式来加载了 require.config({ paths : { "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"] } }) callback函数中有$参数,这就是依赖的jquery模块的输出变量,如果你依赖多个模块,可以依次写入多个参数来使用: require(["jquery","underscore"],function($, _){ $(function(){ _.each([1,2,3],alert); }) }) 如果某个模块不输出变量值,则没有,所以尽量将输出的模块写在前面,防止位置错乱引发误解 require会默认的将data-main指定的js为根路径,
AMD模块规范 第一种写法: define(function() { return { mix: function(source, target) { } }; }); 第二种写法 有依赖项如下: define(['data', 'ui'], function(data, ui) { // init here }); 第三种写法 直接一个对象 define({ data: [], ui: [] }); 第四种写法 有名模块如下: define('index', ['data','base'], function(data, base) { // todo }); 注:有名模块要移动到其他目录时,JS也要跟着改,所以代码维护方面不好 第五种写法 包装模块如下: define(function(require, exports, module) { var base = require('base'); exports.show = function() { // todo with module base } }); 注:书写格式和nodeJS比较像,可以使用require获取模块,使用exports或者module.exports导出API。 书写requireJS遵循一个文件一个模块。 内部机制: RequireJS加载的每个模块作为script Tag,使用head.appendChild()方法。 在模块的定义时,requireJS等到所有的依赖都加载完毕,会为函数的调用计算出正确的顺序,然后在函数中通过正确的顺序进行调用。 requireJS函数增加了第三个参数errbacks
在模块载入失败回调中可以使用undef函数移除模块的注册。
|