5

我正在兜圈子,试图理解 RequireJS 以及如何使用它来加载当我尝试在模块中使用它们时不显示为未定义的依赖项。

我从 John Papa 的 Pluralsight“带有 HTML5 的 SPA”课程开始。我从来不明白的是,为什么需要在脚本标签中指定每个库,而我认为 AMD 在 requireJS 中的全部意义在于您将责任移交给它及其 data-main 属性以异步加载需要什么。该课程中提出的解决方案令人倍感困惑的是,它没有遵循 RequireJS 文档中记录的整个数据主设置。

再过几个月,我们现在有了带有 Durandal 的“热毛巾”模板、一个示例“服务”模块、一个遵循 RequireJS 文档的设置和一个相当容易理解的入门应用程序。唯一能敲响警钟的是,大多数库都位于通常的“脚本”文件夹中,而 Durandal 与应用程序逻辑一起位于完全独立的“应用程序”文件夹中。如果我从pluralsight SPA 课程中学到一件事并使用requireJS,那就是将东西从单个文件夹中移出,事情很快就会变得非常混乱。

无论如何,新模板工作正常。模块依赖关系很好,视图和视图模型是绑定的,并且有一个示例记录器模块,其模块依赖于 Durandal 模块(即在应用程序文件夹中),效果很好。根据 Hot Towel 模板中的代码添加另一个使用 jQuery 和 mockJson 的简单模块应该很简单,对吧?呃,不,不是真的。

这是一个非常简单的声明,用于在“app/services”文件夹中启动我的模块“dataservice.js”

define(['jquery'],
function ($) {
    var init - function....

当我尝试在我的代码块中访问它时,我当然会为 $ 得到“未定义”。因此,在阅读了太多令人困惑的文献之后(其中大部分最终都以评论说“这在 jquery xxxx 中发生了变化,因此不再相关”),我有以下问题:

  1. 当我监控网络流量时,我可以看到 jQuery 库正在正确下载,如果我将其添加到 BundleConfig.cs 中定义的“供应商”捆绑包中,mockJSON 也是如此,所以 jQuery 在那里并在我的浏览器中等待,即使我没有我自己没有给它一个模块定义。要摆脱模块文档中的“未定义”引用似乎意味着我需要添加如下内容:

    require.config({
        paths: {
            'text': 'durandal/amd/text',
            jquery: '../Scripts/jquery-1.9.1'
        }
    });
    

    (“文本”声明已经存在。我刚刚添加了 jquery 别名)这导致我的模块有一个函数而不是“未定义”,它解决了部分问题,除了它导致我已经复制的脚本的第二个副本由于 Hot Towell 模板“供应商”捆绑包而下载。出于明显的原因,我不想下载两份 jQuery,那么我该如何解决这个问题?

  2. 我已将 mockJSON 库添加到我的“供应商”捆绑包中,这通常使用 $.mockJSON 来引用,我无法做任何事情来使其有效。即使我使用与 jquery 相同的过程对脚本的引用进行了破解,我使用 'require.config({paths:' 声明我得到了未定义,更不用说已经提到的'库被下载了两次'的问题. 如何获得定义的库依赖项,以便在模块中使用该库?

  3. 我猜所有这些痛苦都与 requireJS 是关于下载异步模块的事实有关,但 jQuery 和 mockjson 是同步的,所以我必须通过其他方式下载它们(捆绑硬编码参考)但这仍然意味着我的 requireJS模块需要一种将它们声明为依赖项的方法,而我尝试过的任何方法都不起作用。我关于这是一个同步/异步问题的假设是否正确?我曾希望在 Durandal 中找到至少一个使用 jQuery 的示例应用程序,最好是一个 jquery 插件,但我只能看到使用 Durandal 模块而不是其他任何东西的模块代码。所有这些库都在 requireJS 的主根之外的事实可能会加剧问题,因为我不得不求助于其中包含“../”字符串的路径来获取引用。

  4. 我知道 requireJS 在定义命令上使用“约定优于配置”,因此如果我错过了模块 ID,那么它会根据模块源文件名和使用 data-main 指定的已定义根文件夹的路径假定一个 ID。然而,Durandal 在其代码中引用了一个名为“入口”的模块。这个模块不在根文件夹中,而是在一个名为“Durandal/transitions/entrance.js”的文件夹中,所以我很困惑为什么对它的任何引用都是“入口”而不是“Durandal/transitions/entrance”。它在哪里被别名?

  5. 最后(hoorah)我还没有掌握将依赖项指定为定义语句的第一个参数(字符串数组)与省略这些依赖项之间的细微差别,但是在模块工厂中,它成为第一个参数,指定类似 var system = require('../system') - 为什么我会优先使用一种形式而不是另一种形式。我看到这两种类型在示例应用程序中混合在一起,但不明白为什么。

PS:当我编辑此条目时,我看到编号为 1 到 5 的五个问题。当我查看它时,我看到它被渲染为 1,然后是 1 到 4。一些奇怪的 HTML 编辑器与渲染错误,无论我尝试什么格式,我都没有'无法修复,所以请发表任何评论,就好像有五个问题编号为 1 到 5 而不是 2 个编号为 1 和三个编号为 2 到 4!)

4

4 回答 4

2

哇,这是很多问题!

查看 durandal 谷歌组上的这篇文章: https ://groups.google.com/forum/#!searchin/durandaljs/papa/durandaljs/Ku1gwuvqPQQ/gupgNqGIK1MJ

该线程中有趣的一点是,Hot Towel 模板的作者 John Papa 建议使用脚本标签或捆绑包预先加载所有第三方库,然后仅对您自己的模块使用 require/AMD 方法。然后,您自己的模块应该引用 jquery ($) 和 knockout (ko) 的全局属性。

我认为,如果您预先加载第三方模块,然后通过 require/AMD 加载,那么您可能会遇到不可预知的错误,其中一些代码使用全局代码,一些代码使用 AMD 版本。(这似乎在淘汰赛中尤其常见)。

我承认,这种方法在架构上并不那么干净,但是我自己已经在 durandal 上埋头苦干了 5 天,我开始更喜欢预先加载已知的第三方库。

于 2013-03-01T15:51:03.250 回答
1

哦,看在皮特的份上!我无法涉足这一切。

如果您一心想要注入 jQuery 和淘汰赛等,请将其放入您的 main.js 中,在第 6 行附近,然后再进行定义。

var根=这个;// 全局命名空间,窗口

// 以下内容已经通过包加载
// 将它们放在根对象中。将它们添加为服务。
define('jquery', [], function () { return root.jQuery; });
define('ko', [], function () { return root.ko; });
define('breeze', [], function () { return root.breeze; });
define('Q', [], function () { return root.Q; });
定义('时刻',[],函数(){返回root.moment;});
define('sammy', [], function () { return root.Sammy; });
define('toastr', [], function () { return root.toastr; });

使满意?:)

于 2013-03-02T02:10:37.710 回答
0

快速代码答案如下。某处(大概在 Durandal 中)使 jQuery 可用,而没有任何使用它的模块必须将其声明为依赖项(我猜在 Durandal 代码中的某处有一个定义语句,但没有特定示例很难实现这一点。我猜很少人们正在使用 jQuery 或插件(讽刺))。希望 John Papa 即将推出的“热毛巾”课程能够解决其中一些问题/问题。不仅是 jQuery 本身,还有插件。

**解决 jQuery 插件问题的技巧,这是我的团队提出的所有问题背后的真正问题,是 main.js 文件开头的以下命令,该命令由对 requireJS 的脚本引用指向:

require.config({
paths: {
    'text': 'durandal/amd/text',
    'mockjson': '../Scripts/jquery.mockjson.js'
},
shim: {
    'mockjson': {
        deps: ['jquery'],
        exports: ['mockJSON']
    }
}

});

请注意,mockJSON 库需要添加到一个包中(我使用了“供应商”,但您可以添加一个新包),这里的关键点是,由于它是一个 jQuery 插件,您不应该将其声明为任何依赖项您需要它的模块(或者至少这对我有用)。

很抱歉原始问题的长度,但现实是我有一个团队想要这些问题的答案,在网络上找不到它们,在撰写本文时只有 John Papa 的 Code Camper 应用程序可以继续 -如果您想编写大量管道代码以将各种库连接在一起,那么它是一个很好的课程并且是一个很好的起点的应用程序(我们没有。我们需要高效,尽管代码是理解什么的好方法Durandal 等较新的框架正在通过更简单的“约定优于编码”方法为您编码)。对于我们团队而言,该课程的问题在于,当您深入研究代码时,您最终会遇到比找到答案更多的问题(例如“ 为什么当我将库移动到它们自己的子文件夹而不是一个大文件夹中的所有内容时,requireJS 会抛出一个错误,上面写着“你在我背后加载库。让我来做,不要在我背后做” , “为什么代码似乎可以使用一些不在捆绑包中的库,并且搜索仅显示在'more.info.txt'文件中,其用法/意图从未被解释过?”;“为什么模块命名约定在点分隔符和斜杠分隔符之间没有明显的原因(或至少从未解释过?” “为什么捆绑包中引用了解决方案中不存在的脚本文件(是它只是在应用程序的演变过程中未移除的未使用的碎片)?" "

很抱歉,沃德显然不认为试图理解这些东西是如何组合在一起并发挥作用的很重要(这就是为什么我问了我所做的五个问题——我的整个团队都在问的问题,但在任何一个问题中都没有解释围绕 jquery 的“剪切和粘贴”答案和我们在网上找到的要求)。作为一名培训师,我希望他能够理解“给我一些 Pluralsight 课程中的一些删减和过去的代码,这些代码并不真正相关。我不需要理解这不是我在这里想要做的,有时如果可用的材料不能回答一大堆问题,那么整个群体都在努力解决,那么尝试和解释是有意义的你不明白的是什么。我的错!

我想这里有机会让某人写一门像样的 requireJS 课程;-)

于 2013-03-02T07:36:16.460 回答
0

对于后来者来说什么是值得的。Durandal 改进了有关此问题的文档。下面页面中的“配置依赖项”部分解释了使用 define(alias, globalVariable) 注册模块与使用路径和 shim 策略之间的区别。

两者都可以,但如果你使用 path 和 shim,所有依赖项都必须以类似的方式注册。对于使用“jQuery.fn.extend...”的插件来说尤其如此。

http://durandaljs.com/documentation/Conversion-Guide/

于 2013-10-07T11:44:21.533 回答