require.js学习笔记。

加载JavaScript文件

RequireJS的目的是鼓励代码的模块化,它使用了不同于传统script标签的脚本加载步骤。可以用它来加速、优化代码,但其主要目的还是为了代码的模块化。它鼓励在使用脚本时以module ID替代URL地址。
RequireJs以一个相对于baseUrl的地址来加载所有的代码。页面顶层script标签含有一个特殊属性data-main,require.js使用它来启动脚本加载过程,而baseUrl一般设置到与该属性相一致的目录。

<script data-main="scripts/main.js" src="scripts/requires.js"></script>

baseUrl亦可通过RequireJS config手动设置。如果没有显式指定config及data-main,则默认的baseUrl为包含RequireJS的那个HTML页面的所属目录。
图片描述

<script data-main="js/app.js" src="js/require.js"></script>
//app.js
require.config({
    baseUrl:'js/lib',
    paths:{
        app:'../app'
    }
});
require(['jquery','canvas','app/sub'],function($,canvas,sub){
    //....
})

注意在示例中,三方库如Jquery没有将版本号包含在它们的文件名中。我们建议将版本信息放置在单独的文件中进行跟踪。
理想状况下,没个加载的脚本都是通过define()来定义的一个模块;但是有些浏览器全局变量注入型的传统/遗留库并没有使用define()来定义它们的依赖关系,你必须为此使用shim config来指明它们的依赖关系。如果你没有指明依赖关系,加载可能报错。这是因为基于速度的原因,srequireJS会异步地以无序的形式加载这些库。

data-main入口点

require.js在加载的时候会检查data-main属性:

<script data-main="scripts/main" src="scripts/requires.js"></script>

你可以在data-main指向的脚本中设置模板加载选项,然后加载第一个应用模块。注意:你再main.js中所这是的脚本是异步加载的。所以如果你在页面中配置了其它JS加载,则不能保证它们所依赖的JS已经加载成功。

<script data-main="scripts/main" src="scripts/require.js"></script>
<script src="scripts/other.js"></script>
//main.js
require.config({
    paths:{
        foo:'libs/foo-1.1.3'
    }
});
//other.js
require(['foo'],function(foo){})

定义模块

模块不同于传统的脚本文件,它良好的定义了一个作用域来避免全局名称空间污染。它可以显式的列出其依赖关系,并以函数参数的形式将这些依赖进行注入,而无需引用全局变量。requireJS的模块是模块模式的一个扩展,其好处是无需全局引用其它模块。
RequireJs模块语法允许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的。同时因为无需创建全局变量,甚至可以做到在同一页面上同时加载同一模块的不同版本。
如果一个模块仅含值对,没有任何依赖,则在define()中定义这些值就好了:

define({
    color:'black',
    size:'unisize'
})

如果一个模块没有任何依赖,但需要一个setup工作的函数,则在define()中定义该函数,并将其传给define():

define(function(){
    return{
        color:'black',
        size:'unisize'
    }
})

如果模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,在模块的所有依赖加载完毕后,该函数会被调用来定义该模块,因此该模块应该返回一个定义了本模块的object。依赖关系会以参数的形式注入到该函数上,参数列表与依赖名称列表一一对应。

define(['./cart','./inventory'],function(cart,inventory){
    return{
        color:'blue',
        size:'large',
        addToCart:function(){
            inventory.decrement(this);
            cart.add(this);
        }
    }
})

对模块的返回值类型并没有强制为一定是个object,任何函数的返回值都是允许的。此处是一个返回了函数的模块定义:

define(['my/cat','my/inventory'],{
    function(cart,inventory){
        return function(title){
            return title?(window.title = title):inventory.storeName+''+cart.name;
        }
    }
})

define()中的相对模块名:为了可以在define()内部使用诸如require('./relative/name')的调用以正确解析相对名称,记得将require本身作为一个依赖注入到模块中:

define(['require','./relative/name'],funciton(require){
    var mod = require('./relative/name')
})

或者更好地,使用下述转换为CommonJS模块所设的更短的语法:

define(function(require){
    var mod = require('./relative/name')
})

相对路径在一些场景下格外有用,例如:为了以便于将代码共享给其他人或项目,你在某个目录下创建一些模块。你可以访问模块的相邻模块,无需知道该目录的名称。
生成相对于模块的URL地址:你可能需要生成一个相对于模块的URL地址。你可以将require作为一个依赖注入进来,然后调用require.toUrl()以生成URL:

define(['require'],function(require){
    var cssUrl = require.toUrl('./style.css')
})

如果你定义了一个循环依赖(a依赖b,b同时依赖a),则在这种情形下当b的模块函数被调用的时候,它会得到一个undefined的a。b可以在模块已经定义好后用require()方法再获取(记得将require作为依赖注入进来):

//b.js
define(['require','a'],function(require,a){
    return function(title){
        return require('a').doSomething();
    }
})

一般说你无需使用require()去获取一个模块,而是应当使用注入到模块函数参数中的依赖。循环依赖比较罕见,它也是一个重构代码重新设计的i警示灯。
如果你熟悉CommonJS,你可以考虑使用exports为模块建立一个空object,该object可以立即被其它模块引用。再循环依赖的两头都如此操作之后,你就可以完全持有其它模块了。这种方法仅在每个模块都是输出object作为模块值的时候有效,换成函数无效。

//b.js
define(function(require,exports,module){
    var a = require('a');
    exports.foo = function(){
        return a.bar();
    }
})

或则,如果你使用依赖注入数组的步骤,则可用注入特殊exports来解决:

//b.js
define(['a','exports'],function(a,exports){
    exports.foo = function(){
        return a.bar();
    }
});

JSONP是在javascript中服务调用的一种方式。他仅需简单地通过一个script标签发起HTTP GET请求,是实现跨域服务调用一种公认手段。
为了在RequireJS中使用JSON服务,须要将callback参数的值指定为define。这意味着你可将获取到的JSONP URL的值看成是一个模块定义。
下面是一个调用JSONP API端点的示例。该示例中,JSONP的callback参数为"callback",因此"callback=define"告诉API将JSON响应包裹到一个"define()"中:

require(["http://example.com/api/data.json?callback=define"],
    function (data) {
        //The data object will be the API response for the
        //JSONP data call.
        console.log(data);
    }
);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值