在require js中,是否可以判断脚本是否作为data-main加载?例如,我有一个脚本,既可以用作data-main,也可以用作模块:
// script.js
if (this_is_data_main()) {
console.log('do something main');
} else {
console.log('do something else');
}我可以通过将信息写为全局变量来考虑黑客攻击,例如:
//index.html
<!doctype html>
...
<script> window.app.main = 'script'; </script>
<script data-main="script.js" src="require.js"></script>更新的script.js:
// script.js
if (window.app && window.app.main === 'script') {
console.log('do something main');
} else {
console.log('do something else');
}发布于 2017-03-01 20:29:56
摘要
RequireJS不提供做你想做的事情的“官方”方式。有一种非官方的方式,它是脆弱的。但是,我认为您不应该依赖于检测您的脚本是否通过data-main加载。
冗长的解释
RequireJS不提供直接的方法来完成您想要做的事情。如果您阅读了RequireJS的代码,您将看到它显示为data-main并最终将其附加到当前配置的deps选项中。除了一点路径计算之外,没有其他的处理。(路径计算细节对于您在这里提出的更大的问题并不重要,所以我跳过这些细节。)在使用data-main完成RequireJS时,问题中的代码大致相当于:
<script src="require.js"></script>
<script>
require.config({
deps: ["script"]
});
</script>您可以检查deps并查看您的模块是否在其中。你会在这个位置require.s.contexts._.config.deps找到deps。顺便说一下,下划线是默认上下文的名称。但是,从这个奇怪的位置可以看出,它使用的是一个私有API,这个私有API可能会随着RequireJS的未来版本而改变。这是一个问题。另一个问题是,如果使用deps值再次调用require.config,deps的第一个值将被覆盖。因此,根据情况的不同,这将失败。对我的口味来说太脆了。
最终,我不会依赖于模块行为取决于模块是否通过data-main中列出的方式加载,而不是通过其他方式加载。我已经在上面展示了一个等同于使用data-main的方法。这是另一个:
<script src="require.js"></script>
<script>
require(["script"]);
</script>我还可以列出一堆其他的变体。的要点是,从模块加载的角度来看, data-main 是一种便利。它不应该被赋予比方便更重要的意义,我已经在不同的上下文中使用了data-main和上面显示的两个替代方案。上下文通常会决定哪些选项是可能的或可取的。例如,我已经回答了关于OP在哪里运行的问题,在运行他们自己的代码时,RequireJS已经加载了。所以他们甚至不能依赖于data-main。(例如,在较大的框架中充当插件的组件可能会发生这种情况:该框架使用RequireJS,因此它使RequireJS可用于插件,但插件仅限于添加script元素。)
依赖data-main的另一个问题是这是RequireJS的事情。可以使用其他工具加载AMD模块,如SystemJS或捆绑AMD模块使用其他工具,如Webpack。如果您的代码依赖于 data-main ,则在使用这些其他工具时将无法正常工作。
您可以让您的主模块导出一个初始化函数,该函数接受选项并在用户需要时配置您的模块。
如果您想要在模块加载时立即生效而不必调用任何函数,一种不污染全局JavaScript空间的方法是让您的模块查找具有类型application/json的众所周知的script元素(特定的id或特定的class)。因为它是JSON,所以浏览器不会执行它,但需要它的脚本可以访问它。它将包含一个JSON对象,您的模块将读取该对象以进行配置。This question处理如何从脚本中提取JSON。
https://stackoverflow.com/questions/42517151
复制相似问题