web学习 -- AMD 规范

模块规范

AMD规范是异步加载模块的,允许指定回调函数。

定义模块

define方法用于定义模块,RequireJS要求每个模块放在一个单独的文件里

按照是否依赖其他模块,可以分成两种情况讨论。、

  • 第一种情况是定义独立模块,即所定义的模块不依赖其他模块;
  • 第二种情况是定义非独立模块,即所定义的模块依赖于其他模块。

定义了一个alpha模块,并且依赖于内置的require,exports模块,以及外部的beta模块。可以看到,第三个参数是回调函数,可以直接使用依赖的模块,他们按依赖声明顺序作为参数提供给回调函数。

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {

  exports.verb = function() {

         return beta.verb();

      //或者:

      return require("beta").verb();
  }

});

注:这里的require函数让你能够随时去依赖一个模块,即取得模块的引用,从而即使模块没有作为参数定义,也能够被使用;exports是定义的alpha 模块的实体,在其上定义的任何属性和方法也就是alpha模块的属性和方法。通过exports.verb = …就是为alpha模块定义了一个verb方法。例子中是简单调用了模块beta的verb方法。

匿名模块

define 方法允许你省略第一个参数,这样就定义了一个匿名模块,这时候模块文件的文件名就是模块标识。如果这个模块文件放在a.js中,那么a就是模块名。可以在依赖项中用"a"来依赖于这个匿名模块。这带来一个好处,就是模块是高度可重用的。你拿来一个匿名模块,随便放在一个位置就可以使用它,模块名就是它的文件路径。这也很好的符合了DRY(Don’t Repeat Yourself)原则。

下面的代码就定义了一个依赖于alpha模块的匿名模块

define(["alpha"], function (alpha) {
  return {
      verb: function(){
          return alpha.verb() + 2;
      }
  }; 
});

独立模块

如果定义的模块是独立模块,不需要依赖其他任何模块,可以直接用define方法生成

define({
    method1: function() {},
    method2: function() {},
});
define(function () {
    return {
        method1: function() {},
        method2: function() {},
    };
});

注:define定义的模块可以返回任何值,不限于对象

非独立模块

如果被定义的模块需要依赖其他模块,则define方法必须采用下面的格式

define(['module1', 'module2'], function(m1, m2) {
   ...
});

注:

  • define方法的第一个参数是一个数组,它的成员是当前模块所依赖的模块。比如,[‘module1’,
    ‘module2’]表示我们定义的这个新模块依赖于module1模块和module2模块,只有先加载这两个模块,新模块才能正常运行。一般情况下,module1模块和module2模块指的是,当前目录下的module1.js文件和module2.js文件,等同于写成[’./module1’, ‘./module2’]。
  • define方法的第二个参数是一个函数,当前面数组的所有成员加载成功后,它将被调用。它的参数与数组的成员一一对应,比如function(m1, m2)就表示,这个函数的第一个参数m1对应module1模块,第二个参数m2对应module2模块。这个函数必须返回一个对象,供其他模块调用。

新模块返回一个对象,该对象的method方法就是外部调用的接口

define(['module1', 'module2'], function(m1, m2) {

    return {
        method: function() {
            m1.methodA();
            m2.methodB();
        }
    };

});

简单写法:

define(
    function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2'),
            dep3 = require('dep3'),
            dep4 = require('dep4'),
            dep5 = require('dep5'),
            dep6 = require('dep6'),
            dep7 = require('dep7'),
            dep8 = require('dep8');
    }
});

实际运用
返回一个具有plot接口的对象

define(['math', 'graph'], 
    function ( math, graph ) {
        return {
            plot: function(x, y){
                return graph.drawPie(math.randomGrid(x,y));
            }
        }
    };
);

判断浏览器是否为IE

define(('__proto__' in {} ? ['zepto'] : ['jquery']), function($) {
    return $;
});

注:定义了一个中间模块,该模块先判断浏览器是否支持proto属性(除了IE,其他浏览器都支持),如果返回true,就加载zepto库,否则加载jQuery库

调用模块

require方法用于调用模块

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

注:上面方法表示加载foo和bar两个模块,当这两个模块都加载成功后,执行一个回调函数。该回调函数就用来完成具体的任务。

require的第一个参数标识一个表示依赖关系的数组

require( [ window.JSON ? undefined : 'util/json2' ], function ( JSON ) {
  JSON = JSON || window.JSON;
  console.log( JSON.parse( '{ "JSON" : "HERE" }' ) );
});

注:上述代码加载JSON模块时,首先判断浏览器是否原生支持JSON对象。如果是的,则将undefined传入回调函数,否则加载util目录下的json2模块。

require方法也可以在define内部

define(function (require) {
   var otherModule = require('otherModule');
});

require方法的第三个参数,即处理错误的回调函数,接受一个error反对作为参数

requirejs.onError = function (err) {
    // ...
};

注:方法中没有被捕获的错误都会触发监听函数

动态加载模块

define(function ( require ) {
    var isReady = false, foobar;
 
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });
 
    return {
        isReady: isReady,
        foobar: foobar
    };
});

注:上面代码所定义的模块,内部加载了foo和bar两个模块,在没有加载完成前,isReady属性值为false,加载完成后就变成了true。因此,可以根据isReady属性的值,决定下一步的动作。

define(['lib/Deferred'], function( Deferred ){
    var defer = new Deferred(); 
    require(['lib/templates/?index.html','lib/data/?stats'],
        function( template, data ){
            defer.resolve({ template: template, data:data });
        }
    );
    return defer.promise();
});

注:上面代码的define方法返回一个promise对象,可以在该对象的then方法,指定下一步的动作。

如果服务器端采用JSONP模式。则可以直接在require中调用,方法是指定JSONP的callback参数为define。

require( [ 
    "http://someapi.com/foo?callback=define"
], function (data) {
    console.log(data);
});

实际应用

//定义M模块,本申明一个全局变量
define('M',[],function(){
    window.M={};
    return M;
})
//定义模块a 依赖模块 M,b,c
define('a',['M','b','c'],function(M){
    alert(M.ob);
    alert(M.oc);
})
//定义b模块
define('b',[],function(){
    M.ob = 2;
    return M;
})
//定义c模块
define('c',[],function(){
    M.oc = 3;
    return M;
})
//引入a模块
require(['a'],function(a){
    
})

注:

  • M模块的作用是定义一个全局的变量;
  • a模块依赖了其他模块,但是function 参数缺只有M一个参数,但是也可以用使用b,c两个模块里边的变量,这是因为 M 模块里边的全局变量。可以看得出 b,c模块里边的变量在申明的时候就是挂在全局变量下的。所以a模块依赖了b,c模块缺没有使用参数接口,也可以用的原因。
  • 反之,变量没有挂在全局变量下,引用了模块,没有用参数接受,这样是不可以使用其他模块下边的变量和方法的,因为很简单是作用局的问题。
  • 还有就是b,c模块没有引用M模块缺使用了,M模块下边的变量,也是因为此变量是全局变量。如果是局部变量,那就要依赖于M模块才可以使用了。
  • 假如说,反正b,c两个模块也不用参加接收,都挂在了全局变量下边,是不是不引也可以,直接引一个M模块好了。这肯定是不行的,会弹出 undefined
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值