在 require.js 模块中使用 D3.JS 和 sankey 插件

Using D3.JS and the sankey plugin in a require.js module

我正在尝试构建一个 requirejs 模块,为客户端代码提供使用 d3.js. The first plugin I want to use is a sankey diagram 呈现内容的选项。 到目前为止我的模块:

define(['d3'], function(ignore) {

    console.log("bef", d3);
    require(['sankey.js']);
    console.log("aft", d3);
    d3.sankey();

    return {
        ...
        d3: d3,
        renderSankey: function(options) {
           ...
        }
    }

sankey.js脚本使用全局d3变量并添加函数sankey()。 (顺便说一句,define(['d3'], function(ignore)define(['d3'], function(d3) 我都试过了,结果完全一样)。 错误:TypeError: d3.sankey is not a function,无论我是尝试直接调用它,如代码所示,还是像 renderSankey 函数中的 this.d3.sankey()

控制台输出显示(两次,在 require(...) 调用之前和之后:

sankey: d3.sankey()

无论我怎么尝试,都行不通。我觉得我错过了一些关于阴影的 JS 特定内容,但是为什么有一个 sankey 函数,当我 console.log 对象和一行之后,当我尝试调用时出现错误?我做错了什么?

信息:

/编辑:这里是 Require 配置(由 Splunk 仪表板提供)

require.config({
    baseUrl: "{{SPLUNKWEB_URL_PREFIX}}/static/js",
    waitSeconds: 0 // Disable require.js load timeout
});

您用来加载 sankeyrequire 调用是异步的。它将启动 sankey 的加载,但到 require returns 时,sankey 尚未加载。您应该将代码更改为:

define(['d3', 'sankey'], function (d3) {
    d3.sankey();

我认为 d3 也在全局 space 中泄漏了符号 d3 但 AMD 模块不应该依赖全局符号,除非它们是运行时环境的一部分(例如window, document).

您还需要设置 RequireJS 配置,使 sankey 依赖于 d3,因为上面的 define 本身 无法确保d3 将在 sankey 之前加载。所以你需要在你的配置中这样做:

shim: {
    sankey: ['d3']
}

这使得 sankey 依赖于 d3。 (请注意,shim 只能用于影响非 AMD 模块文件的加载。sankey 不会调用 define 来注册自身,因此不是适当的 AMD 模块,我们可以用 shim 作为它。)

此外,模块名称通常不应包含 .js,因此当您要加载插件时,将其加载为 sankey,而不是 sankey.js

好吧,我想@Louis 和我只是误会了对方。这可能是我自己的愚蠢造成的,因为我不知道 require.js 的配置可以在任何地方完成(而且不仅仅是在根文件中一次)。然而,为了仍然获得 Splunk 特定部分,我 post 这个答案(而不是接受 Louis'):

我在我的 splunk 环境中添加了一个新应用程序到(可视化应用程序)。我实际上首先配置依赖项(在其他 splunk 应用程序可加载的 d3-viz 模块中):

require.config({
    paths: {
        'd3': '../app/D3_Viz/d3',         // d3.js
        'sankey': '../app/D3_Viz/sankey', // sankey.js 
        'XYZ': 'all the paths go here'
    },
    shim: {
        'sankey': ['d3'],
        'XYZ': ['d3'],
         // all the dependecies go here
    }
});

define(['splunkjs/ready!', 'jquery', 'd3'],
    function(mvc, $, ignore) {

    var d3Vis =  {
        ...
        renderSankey: function(options) {
            // load dependencies dynamically 
            require(['sankey'], function() {
                // actually render things
            });
        },
        renderXYZ: function(options) {
            require(['XYZ'], function() {
                ...
            });
        },
        ...


        }
    }
    return d3Vis;

我所有的依赖项都可以在 viz-app 中配置(而不是在使用该应用程序的客户端代码中,这是我对 require.js 的根本误解);唯一要做的就是加载 app/viz 作为一个整体(在这个例子中,在 HTML 仪表板中:

require([
    "splunkjs/mvc",
    "splunkjs/mvc/utils",
    "splunkjs/mvc/tokenutils",
    "underscore",
    "jquery",
    "splunkjs/mvc/simplexml",
    "splunkjs/mvc/headerview",
    "splunkjs/mvc/footerview",
    ...
    "../app/D3_Viz/viz"
    ],
    function(
        mvc,
        utils,
        TokenUtils,
        _,
        $,
        DashboardController,
        HeaderView,
        FooterView,
        ...
        d3Viz
    ){
        ... splunk specific stuff
        // No dependencies have to be configured 
        // in the client code
        d3Viz.renderSankey({...});
    }
);