【问题标题】:Defining the jQuery dependency for a module with Durandal in the HotTowel SPA在 HotTowel SPA 中使用 Durandal 定义模块的 jQuery 依赖项
【发布时间】:2013-02-15 01:50:35
【问题描述】:

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

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

再过几个月,我们现在有了带有 Durandal 的“热毛巾”模板、一个示例“服务”模块、一个遵循 RequireJS 文档的设置和一个相当容易理解的入门应用程序。唯一能敲响警钟的是,大多数库都位于通常的“脚本”文件夹中,而 Durandal 与应用程序逻辑一起位于完全独立的“应用程序”文件夹中。如果我从复数 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 的主根之外的事实可能会加剧问题,因为我不得不求助于其中包含“../”字符串的路径来获取引用。有谁知道为什么存在这种“除 Durandal 之外的所有库都在一个文件夹中,但 Durandal 完全独立于一个文件夹中”的结构?

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

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

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

【问题讨论】:

    标签: javascript jquery requirejs durandal hottowel


    【解决方案1】:

    哇,这么多问题!

    查看 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 天,我开始更喜欢预先加载已知的第三方库。

    【讨论】:

    • 感谢您的链接。很高兴知道,如果我们不遵循该线程中讨论的方法,我们可能会在使用 Knockout 时遇到一些问题。我得到了一个解决方案,我现在将发布。
    • 如果您预先加载第 3 方模块,您不必担心为这些模块定义。当他们加载时,他们不知道 require (因为它在那之后加载),所以他们只是加载到全局空间中。如果你经常使用这些(比如 $ 和 ko),那很好。如果你混合搭配,是的,那可能会很尴尬。但是没有理由在 AMD 中混合和匹配一些 3rd 方库,而有些则没有。你当然可以使用 AMD 的所有库(以及不支持它的 shim 库),就像我在 Code Camper 中所做的那样。但是在现实世界的应用程序中你会发现问题,这就是为什么 CodeCamper 的配置很有趣
    • 谢谢约翰。我真的认为它需要在下一个 SPA 课程中进行更多解释。
    • Ian - 您正在寻找 AMD 和 require.js 的更深层次,这是完全可以理解的。大多数开发人员不想深入研究这些深度。我去过那里,它可能很丑:) AMD 课程肯定有空间。我个人对探索 AMD 的所有工作方式不感兴趣。别人肯定可以。我在课程中使用的 AMD 模式取得了巨大的成功(即将推出 1 种模式)并且没有回头。
    【解决方案2】:

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

    如果您一心想要注入 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; });

    满意吗? :)

    【讨论】:

    • 说实话。对于初学者,我使用的是 Durandal,事实证明 jquery 已经以某种方式被神奇地定义了。因此,在发布上述内容后,我发现我不必注入它就在那里。您提供的“剪切和粘贴”代码看起来像是直接来自“Code Camper”应用程序,坦率地说只是令人困惑,因为它不遵循 requireJS 文档中的“使用 db-main”规则(以及它所有的“你需要下载我们的特殊库,其中包含需要 AND jquery”混淆)推荐并且“热毛巾”模板也使用。
    • 我上面提到的所有库“都在那里”。正如在其他地方所说,Durandal(和 HotTowel)决定全局加载它们,这样你就可以使用它们了。但是,如果您根据实践和原则确定注入所有依赖项,这是一个很好的方法。是的,这也是 John 在 CC 中为此目的使用的技术。理解它,您将了解有关 Require 的一些知识,而不是成为那些不太清楚的文档的奴隶。
    • 我觉得我在这里度过了土拨鼠日。您抱怨我最初的问题太长了,我解释说,鉴于 SPA Pluralsight 课程中的很多此类内容缺乏文档和缺乏真正的解释,这就是我问这些问题的原因 - 我(和我的团队)需要了解正在发生的事情,特别是我在原始帖子中提出的每一个观点。 “成为不太清楚的文档的奴隶”(或有关该主题的许多问题)正是我在撰写原始帖子时试图避免的。
    【解决方案3】:

    快速代码答案如下。某处(大概在 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' 文件中,其用法/意图从未被解释过? (或者至少一个从未解释过的?” “为什么捆绑包中引用了解决方案中不存在的脚本文件(只是在应用程序的演变过程中没有删除未使用的碎片)?” “为什么作者移动了NetEye IsBusy 指标库在其自己的库之外,并将其重命名为脚本他自己的 'KoLite' 库?”等等

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-13
        相关资源
        最近更新 更多