requireJS的使用_API(1)

摘要:
之前有介绍过requireJS,可以看看,但是不详细,所以今天参考官网来详细介绍一下:1.加载js文件:RequireJS的目标是鼓励代码的模块化,它使用了不同于传统标签的脚本加载步骤。如果没有显式指定config及data-main,则默认的baseUrl为包含RequireJS的那个HTML页面的所属目录。RequireJS的模块是模块模式的一个扩展,其好处是无需全局地引用其他模块。RequireJS的模块语法允许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的。

之前有介绍过requireJS(模块化开发),可以看看 ,但是不详细,所以今天参考官网来详细介绍一下:

1.加载js文件:

RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤。可以用它来加速、优化代码,但其主要目的还是为了代码的模块化。它鼓励在使用脚本时以module ID替代URL地址。

RequireJS以一个相对于baseUrl的地址来加载所有的代码。 页面顶层<script>标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl一般设置到与该属性相一致的目录。下列示例中展示了baseUrl的设置:

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

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

RequireJS默认假定所有的依赖资源都是js脚本,因此无需在module ID上再加".js"后缀,RequireJS在进行module ID到path的解析时会自动补上后缀。可以通过paths config设置一组脚本,这些有助于我们在使用脚本时码更少的字。

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

有时候你想避开"baseUrl + paths"的解析过程,而是直接指定加载某一个目录下的脚本。此时可以这样做:如果一个module ID符合下述规则之一,其ID解析会避开常规的"baseUrl + paths"配置,而是直接将其加载为一个相对于当前HTML文档的脚本:

  • 以 ".js" 结束.
  • 以 "/" 开始.
  • 包含 URL 协议, 如 "http:" or "https:".

一般来说,最好还是使用baseUrl及"paths" config去设置module ID。它会给你带来额外的灵活性,如便于脚本的重命名、重定位等。 同时,为了避免凌乱的配置,最好不要使用多级嵌套的目录层次来组织代码,而是要么将所有的脚本都放置到baseUrl中,要么分置为项目库/第三方库的一个扁平结构,如下:

  • www/
    • index.html
    • js/
      • app/
        • sub.js
      • lib/
        • jquery.js
        • canvas.js
      • app.js

index.html:

<script data-main="js/app.js"src="js/require.js"></script>

app.js:

requirejs.config({
    //默认的相对加载路径
    baseUrl: 'js/lib',
    paths: {
        app: '../app'
    }
});
requirejs(['jquery', 'canvas', 'app/sub'],
    function($, canvas, sub) {
        //加载成功后执行的函数
    });
2.data-main 入口点:

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

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

3.定义模块:

模块不同于传统的脚本文件,它良好地定义了一个作用域来避免全局名称空间污染。它可以显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量。RequireJS的模块是模块模式的一个扩展,其好处是无需全局地引用其他模块。

RequireJS的模块语法允许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的。同时因为无需创建全局变量,甚至可以做到在同一个页面上同时加载同一模块的不同版本。

(如果你熟悉ConmmonJS,可参看CommonJS的注释信息以了解RequireJS模块到CommonJS模块的映射关系)。(----不好意思。我还没研究ConmmonJS,期待下一次的学习喽!!)

一个磁盘文件应该只定义 1 个模块。多个模块可以使用内置优化工具将其组织打包。

(1)简单的值对:

如果一个模块仅含值对,没有任何依赖,则在define()中定义这些值对就好了:

define({
    color: "black",
    size: "unisize"
});

(2)函数式定义:

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

//before returning its module definition.
define(function() {
    //Do setup work here
    return{
        color: "black",
        size: "unisize"
    }
});

(3)存在依赖的函数式定义:

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

看例子:(在shirt.js中定义一个模块,其中cart.js和inventory.js是和它在同一个目录下的)

define(["./cart", "./inventory"], function(cart, inventory) {
        //return an object to define the "my/shirt" module.
        return{
            color: "blue",
            size: "large",
            addToCart: function() {
                inventory.decrement(this);
                cart.add(this);
            }
        }
    }
);

模块函数以参数"cart"及"inventory"使用这两个以"./cart"及"./inventory"名称指定的模块。在这两个模块加载完毕之前,模块函数不会被调用。

严重不鼓励模块定义全局变量。遵循此处的定义模式,可以使得同一模块的不同版本并存于同一个页面上(参见 高级用法 )(But,我没看呢,还。“高级用法”,一会看一下吧。)。另外,函参的顺序应与依赖顺序保存一致。

返回的object定义了"my/shirt"模块。这种定义模式下,"my/shirt"不作为一个全局变量而存在。

(4)将模块定义为一个函数:  

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

//A module definition inside foo/title.js. It uses
//my/cart and my/inventory modules from before,
//but since foo/title.js is in a different directory than
//the "my" modules, it uses the "my" in the module dependency
//name to find them. The "my" part of the name can be mapped
//to any directory, but by default, it is assumed to be a
//sibling to the "foo" directory.
define(["my/cart", "my/inventory"], function(cart, inventory) { //return a function to define "foo/title". //It gets or sets the window title. return function(title) { return title ? (window.title =title) : inventory.storeName + ' ' +cart.name; } } );

(5)简单包装CommonJS来定义模块:

如果你现有一些以CommonJS模块格式编写的代码,而这些代码难于使用上述依赖名称数组参数的形式来重构,你可以考虑直接将这些依赖对应到一些本地变量中进行使用。你可以使用一个CommonJS的简单包装来实现:

define(function(require, exports, module) {
        var a = require('a'),
            b = require('b');
        //Return the module value
        return function() {};
    }
);

该包装方法依靠Function.prototype.toString()将函数内容赋予一个有意义的字串值,但在一些设备如PS3及一些老的Opera手机浏览器中不起作用。考虑在这些设备上使用优化器将依赖导出为数组形式。

更多的信息可参看CommonJS Notes页面,以及"Why AMD"页面的"Sugar"段落.

(6)定义一个命名模块:

你可能会看到一些define()中包含了一个模块名称作为首个参数:

 //Explicitly defines the "foo/title" module:
    define("foo/title",
        ["my/cart", "my/inventory"],
        function(cart, inventory) {
            //Define foo/title object in here.
}
    );

这些常由优化工具生成。你也可以自己显式指定模块名称,但这使模块更不具备移植性——就是说若你将文件移动到其他目录下,你就得重命名。一般最好避免对模块硬编码,而是交给优化工具去生成。优化工具需要生成模块名以将多个模块打成一个包,加快到浏览器的载人速度。

(7)注意事项:

①一个文件一个模块:

每个Javascript文件应该只定义一个模块,这是模块名-至-文件名查找机制的自然要求。多个模块会被优化工具组织优化,但你在使用优化工具时应将多个模块放置到一个文件中。

define()中的相对模块名:

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

define(["require", "./relative/name"], function(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");
});

控制台调试:

如果你需要处理一个已通过require(["module/name"], function(){})调用加载了的模块,可以使用模块名作为字符串参数的require()调用来获取它:

require("module/name").callSomeFunction()

注意这种形式仅在"module/name"已经由其异步形式的require(["module/name"])加载了后才有效。只能在define内部使用形如"./module/name"的相对路径。

(8)循环依赖:

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);
    }
);

JSONP的这种用法应仅限于应用的初始化中。一旦JSONP服务超时,其他通过define()定义了的模块也可能得不得执行,错误处理不是十分健壮。

仅支持返回值类型为JSON object的JSONP服务,其他返回类型如数组、字串、数字等都不能支持。

这种功能不该用于long-polling类的JSONP连接——那些用来处理实时流的API。这些API在接收响应后一般会做script的清理,而RequireJS则只能获取该JSONP URL一次——后继使用require()或define()发起的的对同一URL的依赖(请求)只会得到一个缓存过的值。

JSONP调用错误一般以服务超时的形式出现,因为简单加载一个script标签一般不会得到很 详细的网络错误信息。你可以override requirejs.onError()来过去错误。更多的信息请参看错误处理部分。

(9)Undefining a Module:

有一个全局函数requirejs.undef()用来undefine一个模块。它会重置loader的内部状态以使其忘记之前定义的一个模块。

但是若有其他模块已将此模块作为依赖使用了,该模块就不会被清除,所以该功能仅在无其他模块持有该模块时的错误处理中,或者当未来需要加载该模块时有点用。参见备错(errbacks)段的示例。

如果你打算在undefine时做一些复杂的依赖图分析,则半私有的onResourceLoad API可能对你有用。

免责声明:文章转载自《requireJS的使用_API(1)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Eclipse+APKTool动态调试APKwiki部署下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

深入浅出Node.js(上)

(一):什么是Node.js Node.js从2009年诞生至今,已经发展了两年有余,其成长的速度有目共睹。从在github的访问量超过Rails,到去年底Node.jsS创始人Ryan Dalh加盟Joyent获得企业资助,再到今年发布Windows移植版本,Node.js的前景获得了技术社区的肯定。InfoQ一直在关注Node.js的发展,在今年的两次...

Android的Window类 ——转

Android的Window类(一)Android的GUI层并不复杂。它的复杂度类似于WGUI这类基于布局和对话框的GUI,与MFC、QT等大型框架没有可比性,甚至飞漫魏永明的 MiniGUI都比它复杂许多。您也许会问,这样简单的GUI如何实现浏览器呢?原因很简单,浏览器有自己一套GUI。Android浏览器 (WebKit)的GUI和Android的GU...

前端模块化详解(完整版)

前言 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,此时在JS方面就会考虑使用模块化规范去管理。本文内容主要有理解模块化,为什么要模块化,模块化...

fopen()函数

1.2 文件的输入输出函数 键盘、显示器、打印机、磁盘驱动器等逻辑设备, 其输入输出都能够通过文件管理的方法来完毕。而在编程时使用最多的要算是磁盘文件, 因此本节主要以磁盘文件为主, 具体介绍Turbo C2.0提供的文件操作函数, 当然这些对文件的操作函数也适合于非磁盘文件的情况。 另外, Turbo C2.0提供了两类关于文件的函...

js中实现页面跳转(返回前一页、后一页)

一:JS 重载页面,本地刷新,返回上一页  复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a>  <a href="javascript:location.reload()">重载页面,本地刷新</a>  <a href="javascri...

DELPHI中的消息处理机制(三种消息处理方法的比较,如何截断消息)

DELPHI中的消息处理机制 Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具。由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpascal)语言,并有强大的数据库引擎(BDE),快速的代码编译器,同时又提供了众多出色的构件。受到广大编程人员的青睐。在众多的编程语言(如VB,PowerBuild...