RequireJS:在指定配置中存在路径别名的绝对路径名时不触发require回调



这里有一个路径别名"jquery"在require.js-config 中

Require.JS正在触发"jquery"的Require回调,但如果为jquery模块指定了绝对路径,则不会触发Require回调。

<script type="text/javascript">
    var require = {
        baseUrl    : "../../",
        paths      : {
            'jquery' : '/js/jquery-1.8.3',
        },
    };
</script>
<script type='text/javascript' src='/js/require.js'></script>
<script type="text/javascript">
    require(['jquery'],function(obj) {
        console.info("jquery loaded","alias");
    });
    require(['jquery'],function(obj) {
        console.info("jquery loaded","alias");
    });
    require(['/js/jquery-1.8.3.js'],function(obj) {
        console.info("jquery loaded","absolute path");
    });
</script>

我期望执行上一个require语句中的console.info,但它没有触发。看起来,如果您需要一个路径别名,然后需要绝对路径,则不会触发回调。

这是Require.JS中的一个错误,还是用路径别名和绝对路径触发回调的其他方法?

正确。尝试用两个不同的名称加载相同的模块是不起作用的。有充分的证据表明这是故意的。

RequireJS将模块视为singleton。("singleton ness"的作用域是RequireJS上下文。因此,同一模块可以为一个上下文实例化一次,为不同的上下文实例化第二次,但它永远不会为同一上下文实例化两次。)当RequireJS加载模块时,模块会获取一个名称。如果define调用的第一个参数是字符串,那么名称就是这个字符串。否则,如果没有影响模块加载的map,则名称将是出现在requiredefine调用中的字符串,该调用将模块列为依赖项。因此,使用问题中的配置,如果您使用require(['jquery'], ...或有一个定义为define(['jquery'], ...的模块foo,则在js/jquery-1.8.3中找到的模块的名称为jquery。然后是一个事实,在一个模块内部,你可以通过这样做来获得模块名称:

define(['module'], function (module) {
    console.log("my module name: " + module.id);
});

好的,那么,如果您的模块需要两个不同的模块名称两次,会发生什么呢?请记住,模块是singleton,所以RequireJS不会执行define两次。模块应该获得哪个id

在实践中,几乎总是当同一模块代码以两个不同的名称加载时,这是一个编程错误,而不是开发人员真正想要做的事情。我从未遇到过使用RequireJS的代码库,在那里,将jQuery加载为jquery和使用带有版本号的路径都是有效的。后一种情况确实是错误的。因此,当您尝试用两个不同的名称加载同一个模块时,RequireJS并没有使用某种可能会导致意外的默认行为。这是安全的做法。

现在,如果你真的必须能够用两个名称加载同一个模块,那么你可以这样做,但你必须明确你想要什么:你可以使用map。这将在要使用的模块名称之间建立明确的关系。映射所做的基本上是说"当模块X中的代码需要模块Y加载模块Z时"

map: {
    '*':
        '/js/jquery-1.8.3': 'jquery'
    }
}

这表示"当任何模块(*)中的代码需要/js/jquery-1.8.3加载jquery时"。如果你想知道,这不会导致循环依赖。RequireJS将看到/js/jquery-1.8.3传递给requiredefine,然后检查map并将其转换为jquery,然后在paths中找到jquery并将其转化为/js/jquery-1.8.3,然后添加.js扩展并获取模块。在经过paths之后,它不会返回到map,因为它从paths得到的结果是路径,而不是模块名称(并且map只转换模块名称)。

注意,对于上面的映射,只有一个模块被加载,它被命名为jquery。如果在其中使用module.id,它将始终具有值"jquery",并且不能具有任何其他值。

重要的一点是:不应将.js放在require调用中,否则它将不起作用:require(['/js/jquery-1.8.3'], ...

最新更新