【问题标题】:Requirejs, d3 and nvd3 integrationRequirejs、d3 和 nvd3 集成
【发布时间】:2013-03-18 18:47:41
【问题描述】:

我面临将 集成的问题,我使用require 的shim 找到了一个简单的解决方案。使用 shim 我可以导出一个变量,我还可以定义依赖项:

d3: { exports: 'd3' },
nvd3: {
  exports: 'nv',
  deps: ['d3']
},

这样,我只需用bower安装d3和其他包,然后用require将它们包含进来,真的又快又干净。

尽管如此,我遇到了以下问题:全局 d3 变量和本地变量(注入到所需模块中的变量)之间可能存在一些冲突。这是一个与转换和选择相关的 d3 / require / nvd3 集成问题。我不完全理解这个问题,但我已经可以考虑一些了。

  • jquery 和 require 有同样的问题,他们提供了 noconflict 方法来修复它
  • 许多库都有这种行为,它们导出全局符号,但据我所知,requirejs 没有针对一般问题的现成修复
  • 如果我将所有对 d3 的全局引用重命名为 d3 源,则问题已得到解决。我在注入的模块中仍然有d3,但它不再冲突了

据我所知,所有 d3 功能都以这种方式工作,但其中一个 nvd3 图表的转换中断可能是因为选择或调度程序被覆盖。它需要对 d3 内部的深入了解才能准确地发现错误,但是对全局符号的简单而正确的处理可能会清除所有类似问题。

可能由于 requirejs 处理 shim 依赖项的方式,全局 d3 符号会暴露给 nvd3。无论如何,相同的符号不适用于需要的模块,并且如果注入(包含在模块依赖项中)会以某种方式被覆盖。

我还尝试将 d3 包装在一个模块中并正确返回一个本地 d3 变量,但看起来问题仍然存在。

我还在 this d3 group discussion 上寻求帮助,该网站承载了一些关于 d3 和模块的先前帖子。


我在这里添加了一个测试用例:https://github.com/danse/requirenvd3

【问题讨论】:

    标签: requirejs d3 nvd3 javascript module d3.js requirejs


    【解决方案1】:

    问题似乎不在于您的 RequireJS 配置,而在于您使用的是 d3.v3 而不是 d3.v2。我在您的测试用例中降级了 d3,并且转换效果很好。 (弹出窗口仍然偏向一边,我认为它们不应该如此,但这似乎不是您目前关心的问题。)据我了解,nvd3 与 d3.v3 存在一些问题,这可能是一个。另外,请注意 ddotsenko 的 jsFiddle 中的 d3 版本。这可以解释为什么当您使用自己的 d3.v3 库实现时他的解决方案不起作用。

    【讨论】:

    • 是的,就是这样,我还收到了关于存储库的拉取请求,确认您在说什么,并且 github 项目存在问题(已关闭!?)。关于 ddotsenko fiddle,它实际上也适用于 d3.v3,因为它只是表明我们能够导入对象,而不是 nvd3 可以工作。谢谢
    【解决方案2】:

    首先,你可以绕过shim 你不需要它来为纯JS返回任何东西。只需使用全局变量。

    Loading Angular from CDN via RequireJS is not injected

    其次,虽然shim 对于声明脚本的依赖关系是半有用的,但您也可以明确地这样做:

    require(['path/to/d3.min'], function(){
        // nesting to insure d3 loads before nvd3
        require(
            [
                'path/to/mylogic' // <- AMD module
                ,'path/to/nvd3.min' // <- actually a plain JS file
            ]
            , function(mylogic /*, we ignore what nvd3 returns */){
                window.nv // is available for you
            }
        )
    })
    

    【讨论】:

    • 我在使用全局变量时遇到了一些问题。是否有可能隐藏了普通的全局变量,并且有必要将它们访问到window?也许这只是基本的 javascript 知识,我希望 d3 在全局范围内,但需要的模块无法访问它。你的回答很有趣。最有趣的部分是嵌套技巧。为什么这比 shim 依赖项更好?垫片不正是为此目的而设计的吗?所以我希望他们在require 源代码中使用相同的逻辑,或者使用更好的逻辑。为什么要尝试烘焙自己的解决方案?
    • shim 与嵌套的require - 您在构建零件方面以灵活性为代价。 RequireJS 配置是整个应用程序的配置。当您只使用嵌套的define/require 调用时,特别是如果它们使用相关资源时,您可以在任何 AMD 设置中重用该组件,而无需更改配置。最后,这只是口味问题,但我的口味告诉我不要将配置变成大型数据树。
    • 谢谢,您的回答绝对有用,但我需要对要求有 nvd3 和 d3 直接经验的人,因为我需要更好地了解出了什么问题。我的意思是,即使我正在导入他们的符号,只要 shim 配置正确,这也不应该导致任何冲突。无论如何,让我们等一下,也许你的答案会是最好的
    • 我试图实现你的解决方案(ddotsenko 上面测试用例存储库上的分支),但它没有解决问题
    • 感谢您的努力,但小提琴并不能证明可以解决此问题。这是 nvd3 动画的问题,github 存储库显示了如何重现错误
    【解决方案3】:

    看看我在this main.js file(使用“depend”requirejs 插件)中做了什么,然后在其他需要导出到全局变量的文件中做:

    定义(['d3'],函数(d3){ // 这里的代码... });

    depend 插件非常好,它允许您通过depend!plugin[dependancy1,dependancy2] 设置分层加载(“plugin”在“dependancy1”和“dependancy2”加载后加载。

    【讨论】:

    • 谢谢,但出于这个目的,我更喜欢 ddotsenko 方法或 shim,因为它们允许在每次定义模块时不指定依赖项!
    • 试过了 (require("depend!nvd3[d3]");),没有解决问题
    • 您必须下载并包含依赖插件。见github.com/jrburke/requirejs/wiki/Plugins#wiki-script
    • 你也应该像这样在定义中包含这些:
    • define(['depend!nvd3[d3]'], 函数 (nvd3) {
    猜你喜欢
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    相关资源
    最近更新 更多