让我们假设这是我的config.js或main.js:
require.config({
// paths are analogous to old-school <script> tags, in order to reference js scripts
paths: {
jquery: "libs/jquery-1.7.2.min",
underscore: "libs/underscore-min",
backbone: "libs/backbone-min",
jquerymobile: "libs/jquery.mobile-1.1.0.min",
jquerymobilerouter: "libs/jquery.mobile.router.min"
},
// configure dependencies and export value aliases for old-school js scripts
shim: {
jquery: ["require"],
underscore: {
deps: ["jquery"],
exports: "_"
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
jquerymobilerouter: ["jquery", "backbone", "underscore"],
jquerymobile: ["jquery", "jquerymobilerouter", "backbone", "underscore"]
}
});
require(["jquery", "backbone", "underscore", "app/app.min", "jquerymobilerouter", "jquerymobile"], function ($, Backbone, _, App) {
console.log($);
console.log(Backbone);
console.log(_);
$("body").fadeIn(function () {
App.init();
});
});
如果我理解正确的paths
配置选项可以让你引用的脚本,一拉的<script>
HTML标签内。 假如是这样的话,我还需要别名脚本像jQuery用$
或用下划线_
在我的实际需要下面的语句? 看来奇怪的是,我必须,因为如果引用的jQuery用标准<script>
标记, $
可以在整个脚本会自动使用。 使用它不应该是相同的paths
?
我是新来的shim
配置选项,我的理解已经取代过时的order!
插入。 什么是exports
属性实际上做什么? 它似乎并不创建一个脚本的别名; 例如,如果我设置exports
为下划线"whatever"
,然后尝试console.log(whatever)
,这是不确定的。 那么,有什么意义呢?
怎么会像jQuery脚本可以正常使用“全球?” 也就是说,什么是正确的方法可以使用$
我App.js模块内的别名,或任何其他模块在我的“应用程序”文件夹? 我必须每一个人模块和别名内需要的jQuery $
每一次? 或者就是这样,我在这里做了正确的方法是什么?
我非常感谢这个特殊的脚本以及其他任何批评; 对于Require.js的文件,在我看来,叶不理想; 的事情,我真的很想知道更多关于似乎得到掩盖,让我抓我的头。
只是为了澄清周围任何混乱exports
,它假定任何垫片库附加一个属性,以全球范围内( window
或root
),或者修改已经存在的全局属性(如jQuery插件)。 当requireJS获取命令加载匀依赖,它会检查相匹配的属性在全球范围内exports
是垫片配置的价值,如果它发现它,并将它作为该模块的价值。 如果没有找到它,然后它加载相关的脚本,等待它来执行,然后查找全局符号并将其返回。
记住一个重要的事实是,除非垫片配置包含exports
值,任何init
对配置方法不会被执行。 依赖装载机必须找到该模块的值(这是exports
指定)之前,该模块可以被初始化,这就是为什么如果有一个垫片所需的属性init
该模块。
更新:我还需要指出的是,如果有问题调用模块define
的任何地方,任何垫片的配置你有该模块将被忽略。 这实际上使我有些头疼,因为我想用垫片配置调用jQuery的jQuery.noConflict(true)
方法来未globify jQuery和保持它的作用域只需要它的模块,但不能设法得到它的工作。 (在底部在如何轻松地做到这一点使用地图配置,而不是垫片的配置信息,请参阅更新。)
更新2:在谷歌requireJS A组最近的问题使我意识到,我的解释可能会有些误导,所以我想澄清一下。 RequireJS只会重新使用匀依赖,如果它是通过requireJS加载至少一次 。 也就是说,如果你只是有一个<script>
托管网页上的标签(比如说,例如,下划线),就像这样:
<script src='lib/underscore.js'></script>
<script src='lib/require.js' data-main='main.js'></script>
...你有你的requireJS的配置是这样的:
paths: {
'underscore': 'lib/underscore'
},
shim: {
'underscore': {
exports: '_'
}
}
然后在第一时间你define(['underscore'], function (_) {});
或var _ = require('underscore');
,RequireJS将重新加载下划线库而不是重复使用先前定义window._
,因为据requireJS知道,你从来没有加载下划线。 当然,它可以检查是否_
已经在根范围内定义的,但它没有验证的方式_
这已经有一样你定义的paths
配置。 例如,两个prototype
和jquery
分配自己window.$
默认情况下,如果requireJS假设“窗口。$”是jQuery的时候它实际上是原型,你要在一个糟糕的情况。
所有这一切意味着,如果你混合和匹配脚本加载风格类似的,你的页面会风了这样的事情:
<script src='lib/underscore.js'></script>
<script src='lib/require.js' data-main='main.js'></script>
<script src='lib/underscore.js'></script>
当第二个下划线实例是requireJS加载的一个。
基本上,图书馆通过requireJS将要加载requireJS有它的知识。 然而, 接下来你需要下划线时,requireJS会去“哎,我已经加载的,所以才交回无论exports
值和不担心加载另一个剧本。”
这意味着你有两个真正的选择。 一个是我所认为的反模式:根本不使用requireJS表达对全球脚本的依赖。 也就是说,只要库附加一个全局的根上下文,你就可以,如果没有明确要求的依赖来访问它,事件。 你可以看到为什么这是一个反模式 - 你基本上只是消除了大部分的优点,使用AMD装载机(显式依赖上市和便携性)。
另外,更好的选择是使用requireJS加载一切,那唯一实际的脚本标签,你应该自己创建的程度是最初加载requireJS之一。 您可以使用垫片,但95%的时间它真的并不难AMD的包装增加了脚本,而不是。 它可能需要更多一点的工作转换所有非AMD库是AMD兼容,但一旦你做了一个或两个它变得轻松很多 - 我可以采取任何通用的jQuery插件,并将其转换为AMD模块在不到一分钟。 它通常只是一个加入的事情
define(['jquery'], function (jQuery) {
在顶部,
return jQuery;
});
在底部。 我之所以有“jQuery的”映射到jQuery
,而不是$
的是,我注意到大多数的插件,这些天被包裹在这样一个封闭:
(function ($) {
// plugin code here
})(jQuery);
而且它关注的预期范围是一个好主意。 你可以“jQuery的”肯定映射到$
直接不过,假设插件没有希望找到jQuery
而不是$
。 这仅仅是基本的AMD封装 - 更复杂的一般尝试检测什么样的装载机正在使用(CommonJS的VS AMD VS普通醇”全局),并根据对结果有不同的放置方式。 您可以在谷歌几秒钟找到这样的例子很容易。
更新:我曾经使用支持的解决方法jQuery.noConflict(true)
与RequireJS的工作,但它需要一个非常小的修改jQuery的来源,因为我已经想出了一个更好的方法来完成同样的事情,而无需修改jQuery的。 幸运的是,这么有詹姆斯·伯克,RequireJS的作者,谁把它添加到RequireJS文档: http://requirejs.org/docs/jquery.html#noconflictmap
文章来源: Require.js is hurting my brain. Some fundamental questions about the way it loads scripts/modules