在HotTowel SPA中为具有Durandal的模块定义jQuery依赖项

时间:2013-02-28 18:25:36

标签: javascript jquery requirejs durandal hottowel

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

我开始使用John Papa的Pluralsight" SPA与HTML5"课程。我从未理解为什么需要在脚本标记中指定每个库,当我认为在requireJS中AMD的全部要点是你将责任交给它并且它的data-main属性异步加载时需要什么。对于该课程中提出的解决方案而言,双重困惑的是它没有遵循RequireJS文档中记录的整个数据主要设置。

继续几个月,我们现在有了#34; Hot Towel"模板与Durandal,一个样本"服务"模块,一个遵循RequireJS文档的设置和一个相当容易理解的入门应用程序。唯一听起来像是警钟的想法是,大多数图书馆都是通常的#34;剧本"文件夹,而Durandal是一个完全独立的应用程序'文件夹以及应用程序逻辑。如果我从多元化的SPA课程中学到了一件事并且使用requireJS,那么从一个文件夹中移动东西就会很快变得非常混乱。

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

这是一个非常简单的声明,用于启动我的模块&datusavice.js'在“app / services'内部夹

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

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

  1. 当我监控网络流量时,我可以看到正确下载了jQuery库,如果我将它添加到'供应商那么就是mockJSON。在BundleConfig.cs中定义的bundle所以jQuery就在那里等着我的浏览器,即使我自己没有给它一个模块定义。摆脱未定义的'我的模块文档中的引用似乎暗示我需要添加如下内容:

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

    ('文本'声明已经存在。我刚刚添加了jquery别名)这会导致我的模块有一个函数而不是' undefined'这解决了问题的一部分,除了它导致我已经看过下载的脚本的第二个副本,因为Hot Towell模板'供应商'束。由于显而易见的原因,我不想下载两份jQuery,所以如何解决这个问题呢?

  2. 我已将mockJSON库添加到我的'供应商' bundle和this通常用$ .mockJSON引用我无法做任何事情来使这个有效。即使我使用与jquery相同的进程来修改脚本的引用,使用' require.config({路径:'声明我未定义,更不用说&# 39;库已下载两次'问题已经提到。如何定义库依赖项,以便我在模块中使用该库?

  3. I'猜所有这种疼痛是值得做的事实,requireJS是有关下载异步模块,但jQuery和mockjson是同步的,所以我有通过其它方式下载它们(捆扎硬编码参考)但这仍然意味着我的requireJS模块需要一种方式来表明它们是依赖关系,而我所尝试的并没有尝试。我对这是一个syncrhonoys /异步问题的假设是正确的吗?我本来希望在Durandal中找到至少一个使用jQuery并且理想情况下是jquery插件的示例应用程序,但我只能看到使用Durandal模块的模块代码而不是其他任何东西。所有这些库都在requireJS的主要根目录之外的事实可能会加剧这个问题,因为我不得不求助于带有' ../'的路径。其中的字符串以获取引用。有没有人知道为什么除了Durandal之外的所有图书馆的结构都在一个文件夹中,但Durandal是一个完全独立的文件夹。存在?

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

  5. 最后(hoorah)我避难所'吨掌握指定依赖作为第一个参数(一个字符串数组),以一定义语句VS省略这些依赖但随后在模块工厂变得之间的差的细微之处第一个参数指定类似var system = require(' ../ system') - 为什么我会使用一个表单而不是另一个表单。我看到这两种类型在示例应用程序中混合使用,并且不明白为什么。

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

4 个答案:

答案 0 :(得分:2)

哇,这是很多问题!

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

该主题的有趣之处在于,热毛巾模板的作者John Papa建议使用脚本标签或捆绑包预先加载所有第三方库,然后仅使用require / AMD方法为您自己的模块。然后,您自己的模块应该引用jquery($)和knockout(ko)的全局属性。

我认为,如果您预先加载第三方模块然后通过require / AMD加载,那么您可以使用全局和使用AMD版本的某些代码获得不可预测的错误。 (这似乎特别适用于淘汰赛。)

我承认,这种做法并不像在建筑上那么干净,但是我已经开始倾向于在durandal上工作5天了,我开始更愿意预先加载已知的第三方图书馆。

答案 1 :(得分:1)

哦,为了皮特的缘故!我无法完成所有这些。

如果您已经开始注入jQuery和knockout等等,请将其放在main.js中,在第6行附近,然后再进行定义。

var root = this; // the global namespace, window

// The following are already loaded via bundles 
// which put them in the root object. Add them as services.
define('jquery', [], function () { return root.jQuery; });
define('ko', [], function () { return root.ko; });
define('breeze', [], function () { return root.breeze; });
define('Q', [], function () { return root.Q; });
define('moment', [], function () { return root.moment; });
define('sammy', [], function () { return root.Sammy; });
define('toastr', [], function () { return root.toastr; });

满意? :)

答案 2 :(得分:0)

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

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

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

});

请注意,需要将mockJSON库添加到一个bundle(我使用'vendor'但你可以添加一个新的bundle),这里它们的关键点是因为它是一个jQuery插件你不应该将它声明为一个依赖在任何需要它的模块中(或者至少那些对我有用的模块)。

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

对不起,沃德显然不认为试图理解这些东西如何组合在一起并且正在发挥作用很重要(这就是为什么我问了我所做的五个问题 - 我整个团队提出的问题并没有解释在任何关于jquery的'剪切和粘贴'答案中,并要求我们在网上找到)。作为一名培训师,我希望他能够理解“给我一些切割和过去的代码来自Pluralsight课程并不是真正相关的。我不需要理解它不是我在这里尝试做的事情,有时如果可用的材料没有回答整组问题,那么整群人都在苦苦思索,那么尝试解释是有意义的你不懂的是什么我的坏!

我想这里有机会写一个体面的requireJS课程; - )

答案 3 :(得分:0)

对于后来者来说值多少钱。 Durandal已经改进了有关此问题的文档。下面的“配置依赖关系”部分解释了使用define(别名,globalVariable)和使用路径和填充策略注册模块之间的区别。

两者都有效,但如果使用路径和填充程序,则必须以类似的方式注册所有依赖项。对于使用“jQuery.fn.extend ...”的插件尤其如此。

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