100

我从这里API阅读了requirejs文档

requirejs.config({
    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.
                return this.Foo.noConflict();
            }
        }
    }
});

但我没有得到垫片的一部分。为什么我应该使用 shim 以及我应该如何配置,我可以得到更多的澄清

请任何人举例说明为什么以及何时应该使用垫片。谢谢。

4

3 回答 3

113

shim 的主要用途是与不支持 AMD 的库一起使用,但您需要管理它们的依赖关系。例如,在上面的 Backbone 和 Underscore 示例中:您知道 Backbone 需要 Underscore,因此假设您这样编写代码:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS 将启动对 Underscore 和 Backbone 的异步请求,但您不知道哪个会先返回,因此 Backbone 可能会在 Underscore 加载之前尝试对其执行某些操作。

注意:这个下划线/主干示例是在这两个库都支持 AMD 之前编写的。但该原则适用于当今任何不支持 AMD 的库。

“init”钩子可以让你做其他高级的事情,例如,如果一个库通常会将两个不同的东西导出到全局命名空间中,但你想在一个命名空间下重新定义它们。或者,也许您想对正在加载的库中的方法进行猴子修补。

更多背景:

于 2013-03-18T20:50:55.753 回答
65

根据 RequireJS API 文档,shim 可以让你

为不使用 define() 声明依赖关系和设置模块值的旧的传统“浏览器全局”脚本配置依赖关系、导出和自定义初始化。

- 配置依赖项

假设您有 2 个 javascript 模块(moduleA 和 moduleB),其中一个(moduleA)依赖于另一个(moduleB)。这两个对于您自己的模块都是必需的,因此您可以在 require() 或 define() 中指定依赖项

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

但是由于 require 本身遵循 AMD,因此您不知道会提前获取哪一个。这就是 shim 来拯救的地方。

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

这将确保在加载 moduleA 之前始终获取 moduleB。

- 配置出口

Shim 导出告诉 RequireJS 全局对象(窗口,当然,假设您在浏览器中)上的哪个成员是实际的模块值。假设 moduleA 将自己添加到windowas 'modA' 中(就像 jQuery 和 underscore 分别作为 $ 和 _ 一样),然后我们将导出值设为 'modA'。

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

它将为 RequireJS 提供对该模块的本地引用。全局 modA 仍将存在于页面上。

- 旧的“浏览器全局”脚本的自定义初始化

这可能是 shim 配置最重要的特性,它允许我们添加“浏览器全局”、“非 AMD”脚本(也不遵循模块化模式)作为我们自己模块中的依赖项。

假设 moduleB 是普通的旧 javascript,只有两个函数 funcA() 和 funcB()。

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

尽管这两个函数都在窗口范围内可用,但 RequireJS 建议我们通过它们的全局标识符/句柄来使用它们以避免混淆。所以将垫片配置为

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

init 函数的返回值用作模块导出值,而不是通过“导出”字符串找到的对象。这将允许我们在我们自己的模块中使用 funcB 作为

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

希望这有帮助。

于 2015-01-22T18:52:09.123 回答
-2

您必须在 requirejs.config 中添加路径才能声明,例如:

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});
于 2016-05-19T09:47:31.353 回答