[RequireJS]入门API

来源:互联网 发布:mac系统桌面图标 编辑:程序博客网 时间:2024/05/16 19:07

§ 1. 用法

§ 1.1. 加载js脚本文件

为了鼓励模块化开发,使用模块ID来进行模块代码加载。

RequireJS通过baseUrl的相关路径来进行代码加载。

baseUrl一般设置为 data-main属性对应文件的父目录。

(RequireJS会检查并运行data-main所指定的脚本)

html内设置baseUrl的代码如下:

<!--This sets the baseUrl to the "scripts" directory, and    loads a script that will have a module ID of 'main'--><script data-main="scripts/main.js" src="scripts/require.js"></script>

baseUrl也可以通过config来进行手动设置。

如果没有使用script标签,或config进行设置,baseUrl将会是运行RequireJS的html文件目录。

RequireJS默认以"baseUrl和paths"方式加载脚本,如果不想使用baseUrl和paths的方式加载脚本,可以是使用下面的方法:

1.带".js"结尾

2.以"/"开始

3.含"http:"或"https:"的url地址

 

如果想要清晰的分割目录结果,可以使用下面的方法,但不推荐


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({    //By default load any module IDs from js/lib    baseUrl: 'js/lib',    //except, if the module ID starts with "app",    //load it from the js/app directory. paths    //config is relative to the baseUrl, and    //never includes a ".js" extension since    //the paths config could be for a directory.    paths: {        app: '../app'    }});// Start the main app logic.requirejs(['jquery', 'canvas', 'app/sub'],function   ($,        canvas,   sub) {    //jQuery, canvas and the app/sub module are all    //loaded and can be used here now.});

RequireJS也可以引用用户自己通过define()方法定义的模块,且可以定义该模块的依赖模块

另外,对于浏览器级别的脚本的,不能通过define()来定义依赖模块,需要通过shim config来定义他们的依赖模块

 

§ 1.2. data-main 入口

代码如下:

<!--when require.js loads it will inject another script tag    (with async attribute) for scripts/main.js--><script data-main="scripts/main" src="scripts/require.js"></script>

data-main 可以同时设置config与入口模块

RequireJS无法保证 data-main 模块会优先于 其他通过<script>标签引用的脚本 被加载完成并执行。

例如下面的代码有时会执行失败:

<script data-main="scripts/main" src="scripts/require.js"></script><script src="scripts/other.js"></script>
// contents of main.js:require.config({    paths: {        foo: 'libs/foo-1.1.3'    }});// contents of other.js:// This code might be called before the require.config() in main.js// has executed. When that happens, require.js will attempt to// load 'scripts/foo.js' instead of 'scripts/libs/foo-1.1.3.js'require(['foo'], function(foo) {});

如果想在html使用require()方法,只用引用RequireJS,不要加data-main属性即可,例如:

<script src="scripts/require.js"></script><script>require(['scripts/config']), function() {    // Configuration loaded now, safe to do other require calls    // that depend on that config.    require(['foo'], function(foo) {    });});</script>

 

§ 1.3. 定义模块

模块定义使用了命名空间与作用域来避免冲突

模块罗列了他的依赖模块,并将依赖模块作为参数传入

RequireJS的异步加载模块,使得她速度快,也因为他没有定义全局模块,使得她可以在一个页面里同时加载不同版本的同一个模块。

(RequireJS模块可以转换为CommonJS模块)

每个模块必须定义在一个文件里,这些模块可以通过优化工具,被打包压缩。

 

§ 1.3.1. 简单键/值对[json格式类似] 没有依赖模块,没有方法,只有数据

//Inside file my/shirt.js:define({    color: "black",    size: "unisize"});

§ 1.3.2. 定义方法

没有依赖模块,但需要处理些事情准备时的定义模块方法:

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

§ 1.3.3. 含依赖模块的定义

第一个参数是,依赖模块名数组,第二个参数是回调方法,该回调方法的形参是依赖模块(且顺序一致),返回一个对象

到所有依赖模块加载完毕后,才会调用回调方法,该模块不是全局模块。

代码如下:

//my/shirt.js now has some dependencies, a cart and inventory//module in the same directory as shirt.jsdefine(["./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);            }        }    });

§ 1.3.4. 用方法的形式定义模块

模块返回值不一定为对象,下面就是返回方法的模块定义方法:

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

§ 1.3.5. 简单CommonJS模块的兼容定义

需要直接引用模块名,代码如下:

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

该格式需要Function.prototype.toString()方法获取方法内容,不能在PS3和一些旧Opera浏览器中使用,但在优化工具优化压缩后正常运行。

§ 1.3.6. 定义带模块名的模块

模块名作为define()的第一个参数

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

模块命名一般有优化工具自动生成,也可以自己命名,但是一旦移动目录后,就需要重新命名,不太灵活,而且自动优化工具能过自动命名,并且在一个文件里存放多个模块,可以让浏览器加载更快。

§ 1.3.7. 其他的模块方面的提示:

1.一个js文件,一个模块。 可以使用优化工具,将开发完的所有代码优化后,会进行压缩,整合

2.可以在模块内部使用require方法

define(["require", "./relative/name"], function(require) {    var mod = require("./relative/name");});
define(function(require) {    var mod = require("./relative/name");});

3.生成相对于模块的url

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

4.控制台内的调试

对于已经加载的模块,可以通过下面方法获取他

require(["module/name"], function(){}) 

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

相对路径只在内部定义可用。

§ 1.3.8. 循环依赖

"a" needs "b" and "b" needs "a"

b内的a为null

应该用下面方法:

//Inside b.js:define(["require", "a"],    function(require, a) {        //"a" in this case will be null if "a" also asked for "b",        //a circular dependency.        return function(title) {            return require("a").doSomething();        }    });

也可以使用CommonJS模块的方法,但是必须每个模块返回的都是对象,而不是方法

//Inside b.js:define(function(require, exports, module) {    //If "a" has used exports, then we have a real    //object reference here. However, we cannot use    //any of "a"'s properties until after "b" returns a value.    var a = require("a");    exports.foo = function () {        return a.bar();    };});

//Inside b.js:define(['a', 'exports'], function(a, exports) {    //If "a" has used exports, then we have a real    //object reference here. However, we cannot use    //any of "a"'s properties until after "b" returns a value.    exports.foo = function () {        return a.bar();    };});

§ 1.3.9. 特别的JSONP服务的依赖

JSONP:js通过http Get方法的跨域调用WebService的方法

通过回调参数获取JSONP URL返回的数据

代码如下:

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超时,会导致依赖他的模块无法执行,也无法对JSONP超时做出充分的错误处理

只有JSONP返回JSON数据时,才能使用该方法。返回数组,字符串或数字时,不能使用该方法。且不适用于长轮询JSONP,如果查复通过同一个JSONP URL获取,只能获取到缓存数据

你可以重写requirejs.onError()方法去捕获错误。

§ 1.3.10. 解除模块定义

RequireJS里有一个全局函数requirejs.undef()可以用来解除模块定义,但是无法移除已经依赖完成的模块内的定义,一般用于错误时的处理

 

§ 2. 原理

RequireJS的加载依赖JavaScript模块是通过 head.appendChild() 来实现的

RequireJS会按照正确的顺序加载脚本模块

如果用于服务器端时,可以修改require.load()方法,使得RequireJS同步加载脚本模块

require.load位于 build/jslib/requirePatch.js

 

§ 3. 配置选项

§ 3.1. 可以直接在html内配置

<script src="scripts/require.js"></script><script>  require.config({    baseUrl: "/another/path",    paths: {        "some": "some/v1.0"    },    waitSeconds: 15  });  require( ["some/module", "my/module", "a.js", "b.js"],    function(someModule,    myModule) {        //This function will be called when all the dependencies        //listed above are loaded. Note that this function could        //be called before the page is loaded.        //This callback is optional.    }  );</script>

也可以在data-main入口脚本文件里通过require.config 配置,但请注意,只能有一个data-main入口。

当然也可以在载入requireJS前,定义全局配置对象 require,如下:

<script>    var require = {        deps: ["some/module1", "my/module2", "a.js", "b.js"],        callback: function(module1, module2) {            //This function will be called when all the dependencies            //listed above in deps are loaded. Note that this            //function could be called before the page is loaded.            //This callback is optional.        }    };</script><script src="scripts/require.js"></script>

§ 3.2. 支持的配置选项

baseUrl: 查找所有模块的根目录。通过插件,可以做到跨域加载。

paths: 罗列了不从baseUrl里查找的模块。一般paths是相对于baseUrl的路径,除非是通过'/'或'URL形式'定义的路径

bundles: 打包定义模块,代码如下:

requirejs.config({    bundles: {        'primary': ['main', 'util', 'text', 'text!template.html'],        'secondary': ['text!secondary.html']    }});require(['util', 'text'], function(util, text) {    //The script for module ID 'primary' was loaded,    //and that script included the define()'d    //modules for 'util' and 'text'});

skim: 加载不能用define()定义的模块,如:全局定义,exports等非AMD规则库

例如下面:

requirejs.config({    //Remember: only use shim config for non-AMD scripts,    //scripts that do not already call define(). The shim    //config will not work correctly if used on AMD scripts,    //in particular, the exports and init config will not    //be triggered, and the deps config will be confusing    //for those cases.    shim: {        'backbone': {            //These script dependencies should be loaded before loading            //backbone.js            deps: ['underscore', 'jquery'],            //Once loaded, use the global 'Backbone' as the            //module value.            exports: 'Backbone'        },        'underscore': {            exports: '_'        },        'foo': {            deps: ['bar'],            exports: 'Foo',            init: function (bar) {                //Using a function allows you to call noConflict for                //libraries that support it, and do other cleanup.                //However, plugins for those libraries may still want                //a global. "this" for the function will be the global                //object. The dependencies will be passed in as                //function arguments. If this function returns a value,                //then that value is used as the module export value                //instead of the object found via the 'exports' string.                //Note: jQuery registers as an AMD module via define(),                //so this will not work for jQuery. See notes section                //below for an approach for jQuery.                return this.Foo.noConflict();            }        }    }});//Then, later in a separate file, call it 'MyModel.js', a module is//defined, specifying 'backbone' as a dependency. RequireJS will use//the shim config to properly load 'backbone' and give a local//reference to this module. The global Backbone will still exist on//the page too.define(['backbone'], function (Backbone) {  return Backbone.Model.extend({});});

关于使用 jQuery或Backbone插件,可以通过下面方式定义:

requirejs.config({    shim: {        'jquery.colorize': ['jquery'],        'jquery.scroll': ['jquery'],        'backbone.layoutmanager': ['backbone']    }});
requirejs.config({    shim: {        'jquery.colorize': {            deps: ['jquery'],            exports: 'jQuery.fn.colorize'        },        'jquery.scroll': {            deps: ['jquery'],            exports: 'jQuery.fn.scroll'        },        'backbone.layoutmanager': {            deps: ['backbone']            exports: 'Backbone.LayoutManager'        }    }});

map: 给模块定义前缀,特别用于大型的,能够同时使用依赖模块的不同版本

requirejs.config({    map: {        'some/newmodule': {            'foo': 'foo1.2'        },        'some/oldmodule': {            'foo': 'foo1.0'        }    }});

文件系统:

  • foo1.0.js
  • foo1.2.js
  • some/
    • newmodule.js
    • oldmodule.js

When 'some/newmodule' does `require('foo')` it will get the foo1.2.js file, and when 'some/oldmodule' does `require('foo')` it will get the foo1.0.js file.

只有在AMD规范下才起作用,且必须使用绝对路径。

也支持*号

requirejs.config({    map: {        '*': {            'foo': 'foo1.2'        },        'some/oldmodule': {            'foo': 'foo1.0'        }    }});

Means that for any module except "some/oldmodule", when "foo" is wanted, use "foo1.2" instead. For "some/oldmodule" only, use "foo1.0" when it asks for "foo".

config: 可将配置下发至模块的配置:

requirejs.config({    config: {        'bar': {            size: 'large'        },        'baz': {            color: 'blue'        }    }});//bar.js, which uses simplified CJS wrapping://http://requirejs.org/docs/whyamd.html#sugardefine(function (require, exports, module) {    //Will be the value 'large'    var size = module.config().size;});//baz.js which uses a dependency array,//it asks for the special module ID, 'module'://https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#wiki-magicdefine(['module'], function (module) {    //Will be the value 'blue'    var color = module.config().color;});

也可为包配置:

requirejs.config({    //Pass an API key for use in the pixie package's    //main module.    config: {        'pixie/index': {            apiKey: 'XJKDLNS'        }    },    //Set up config for the "pixie" package, whose main    //module is the index.js file in the pixie folder.    packages: [        {            name: 'pixie',            main: 'index'        }    ]});

packages: 配置从commonJS模式包里加载模块

nodeIdCompat: 使得带js后缀与不带的模块ID相同

waitSeconds: 加载超时时间。0:无超时,默认7秒

context: 多版本支持

deps: 依赖

callback: 依赖模块加载完后的回调

enforceDefine: 若模块没有define()或shim exports string value会报错

xhtml: true时,会用document.createElementNS() 创建脚本元素

urlArgs: URL参数

urlArgs: "bust=" +  (new Date()).getTime()

在开发阶段有用

scriptType: 脚本类型版本,默认:text/javascript

skipDataMain: 跳过入口属性扫描直接加载模块,用于使用多个 由RequireJS开发的模块

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子断奶一直哭怎么办 突然喜欢咬指甲怎么办 孩子喜欢咬指甲怎么办 小孩喜欢咬指甲怎么办 宝宝喜欢咬指甲怎么办 婴儿含奶睡觉怎么办 宝宝2岁还吃母乳怎么办 宝宝总抠屁眼怎么办 一年级的孩子厌学怎么办 孩子就是不说话怎么办 感觉自己反应慢怎么办 小学生数学基础不好怎么办 数学考差了怎么办 孩子考试成绩差该怎么办 大学高数听不懂怎么办 遇上自私的父母怎么办 小孩一年级数学不好怎么办 数学考试考不好怎么办 孩子奥数学不好怎么办 孩子下笔太重怎么办 小孩子写字太重怎么办 经常对小孩发火怎么办 对小孩发火后悔怎么办 小孩子不喜欢学数学怎么办? 孩子心里素质差怎么办 三年级语文太差怎么办 宝宝一年级很笨怎么办 一年级孩子太笨怎么办 孩子学习脑子笨怎么办 四年级孩子数学差怎么办 中考考不好了怎么办 初中没学高中怎么办 数学基础差该怎么办 三年级数学成绩差怎么办 夫妻差6岁怎么办 初一数学很差劲怎么办 三年级孩子成绩差怎么办 初中数学成绩不好怎么办 大人不会算数学怎么办 小学初数学不好怎么办 初中生数学计算能力差怎么办