RequireJS用法

1、概述

requirejs 的相关说明:

RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一。最新版本的RequireJS压缩后只有14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用RequireJS可以提升前端代码质量。

主要特点:
  • 异步加载模块
  • 按依赖顺序加载
  • 模块依赖前置

2、define 和 require

在整个require中,主要的方法为:require和define

(1)define定义模块

函数方法:

define(id?, dependencies?, factory)

总共有三个参数:id 定义的模块名字,一般在config 中会定义;dependencies为需要的依赖模块;factory为定义的模块。其中factory 为必填,另外两个为非必填项。
根据上面的参数配置可以看出,define 总共分为两种,第一种为独立模块,不依赖其他模块。第二种为非独立模块,需要依赖其他模块。
注:define定义的模块可以返回任何值,不限于对象。

独立模块

一种通过一个对象简易定义:

define({
    name: "aimee",
    method1: function() {},
    method2: function() {}
})

*注:这样定义的对象如果被多处引用,那么引用的地方会共享这个对象的引用。
另一种通过一个函数来定义副本对象模块:

define(function () {
    //Do setup work here
    return {
        name: "aimee",
        method1: function() {},
        method2: function() {}
    }
})

这种自由度更高,可以在函数中处理其他逻辑。

非独立模块
需要引入依赖模块,在其他模块加载完,定义自己的模块,此时返回的method方法中包含模块1 和模块2的函数的调用。

define(['module1', 'module2'], function(m1, m2) {
    return {
        method: function() {
            m1.methodA();
            m2.methodB();
        }
    }
})

当定义多个时,可以通过function 函数里接受一个require默认参数来处理。

define(
    [       'dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7', 'dep8'],
    function(dep1,   dep2,   dep3,   dep4,   dep5,   dep6,   dep7,   dep8){
        ...
    }
);

可以这样写:

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

            ...
    }
})
(2)require 调用模块

通过define定义模块后,可以使用require来调用模块。

require(dependencies?, factory, errorCallback)

require的参数有:dependencies 为依赖模块,非必填;factory 处理函数,必填;errorCallback 为 错误的回调,非必填;

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

上述例子,在foo 和 bar 模块加载完成后,再在函数中执行foo 和 bar 的方法,如果有错误则到错误的回调函数中,并接受一个error对象作为参数。

全局error事件监听,所有没有被上面的方法捕获的错误,都会被触发这个监听函数。

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

define中require异步加载

例子中,define定义了一个模块,其中foobar 需要依赖 foo 和bar 模块的方法,由于require 为异步,此时return 的结果可以通过isReady 来判断是否加载完成。

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

可以用过promise 来实现

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

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

小结
require 和 define 函数内部机制差不多,不一样的地方是 define 的回调函数需要有 return 语句返回模块对象,这样 define 定义的模块才能被其他模块引用;require 的回调函数不需要 return 语句。

3、requirejs config 配置

paths:
可以配置模块的引用路径,可以本地相对路径,也可以是外部路径,可以提供多个路径,当第一个失败时,会使用第二个路径。
简单配置如下

require.config({
    paths: {
        jquery: [
            '//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js',
            'lib/jquery'
        ]
    }
});

baseUrl
baseUrl 指定了一个目录,然后requirejs基于这个目录来寻找依赖的模块。
可以通过config 来配置,也可以通过引入requirejs 文件的data-main属性定义。

shim:
用于配置在脚本/模块外面并没有使用RequireJS的函数依赖并且初始化函数。假设underscore并没有使用 RequireJS定义,但是你还是想通过RequireJS来使用它,那么你就需要在配置中把它定义为一个shim。

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

或者:

requirejs.config({
    baseUrl: 'js'
});
4、插件

requirejs 提供多种插件,具体插件详情可以查看文档 插件类型

define([
    'backbone',
    'text!templates.html'
], function( Backbone, template ){
   // ...
});

以上为text 插件,通过在模块名前添加text!来指定插件类型,在回调函数中能够通过template来获取模板的内容,格式为字符串。

5、优化器r.js

requireJS提供一个基于node.js的命令行工具r.js,用来压缩多个js文件。它的主要作用是将多个模块文件压缩合并成一个脚本文件,以减少网页的HTTP请求数。



参考:

官方文档api: requirejs.org
官方文档git:requirejs-git