requirejs API 详解

300 阅读3分钟

加载模块

<!--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>

这个script标签由于使用了data-main属性,因此设置了baseUrl为scripts目录。

baseUrl也可以通过RequireJS config指定。如果没有显示指定 RequireJS config,并且script标签也没有使用data-main属性,则baseUrl默认为当前html文件所在的目录路径。

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

baseUrl 和 path可以使模块的导入语法更简洁。默认情况下,RequireJS还假定所有依赖项都是脚本,因此它不希望在模块ID上看到尾随的“ .js”后缀。

require.config({
    baseUrl: './app'
})
require(['math', 'constants', 'price_cmd'], function(...modules) {
    console.log(modules)
    const Math = modules[0];
    const constant = modules[1]
    console.log('常量对象', constant);
    console.log('fen2yuan', Math.fen2yuan(100));
})

要想屏蔽这种优化行为,按相对于当前文档的相对路径访问,只需要在指定依赖项的时候符合任意以下特征:

  • 以“ .js”结尾。
  • 以“ /”开头。
  • 包含URL协议,例如“ http:”或“ https:

data-main 入口点

data-main属性是一个特殊属性,require.js将检查该属性以开始脚本加载:

<!--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脚本来设置配置选项,然后加载第一个应用程序模块。

注意:RequestJS会为data-main模块生成的script标签包含async属性。这意味着你不能假定data-main脚本的加载和执行在同一页面稍后引用的其他脚本之前完成。

定义模块

模块与传统脚本文件的不同之处在于,它定义了一个有良好作用域的对象,可避免污染全局名称空间。它可以显式列出其依赖关系,获取这些依赖的模块不是通过引用全局变量,而是将依赖关系作为定义模块的函数的参数来接收。RequireJS中的模块是传统设计模式中模块模式的扩展,其优点是不需要全局变量来引用其他模块。 可以通过优化工具将模块分组为优化的捆绑包。

普通键值对

需要导出普通键值对时,直接将对象传递给define函数即可

app/constants.js

define({
    HOST: 'http://tppdev.zjtlcb.com',
    PORT: 8090
})

定义函数

如果不需要任何依赖,但是需要使用一个函数来完成一些设置工作,然后定义自己。将一个函数传递给define函数即可。

app/math.js

define(function() {
    console.log('math called');
    console.log('define.amd', define.amd);
    // 分转元
    function fen2yuan(amt) {
        return (amt/100).toFixed(2);
    }
    return {
        fen2yuan: function(amt) {
            return fen2yuan(amt);
        }
    }
})

定义有依赖的函数

如果模块具有依赖项,则第一个参数应为依赖项名称数组,第二个参数应为定义函数。加载所有依赖项后,将调用该函数以定义模块。该函数应返回定义模块的对象。依赖项将作为函数参数传递给定义函数,并以与依赖项数组中的顺序相同的顺序列出。

main.js

require.config({
    baseUrl: './app'
})
require(['math', 'constants'], function(...modules) {
    console.log(modules)
    const Math = modules[0];
    const constant = modules[1]
    console.log('常量对象', constant); // 常量对象{HOST: "http://localhost", PORT: 8088}
    console.log('fen2yuan', Math.fen2yuan(100)); // fen2yuan 1.00
})

使用简化的CommonJS包装器定义模块

如果有的模块使用CommonJS规范定义的,使用上面的方法并不能对这些模块进行导入以重新处理。这种情况,以使用简化的CommonJS包装器:

app/price_cmd.js

define(function(require, exports, module) {
    const Math = require('../../cmdModule/module/math');
    console.log('Math', Math)
    return {
        ...
    }
})