如何使用 RequireJS 加载依赖于 d3 的脚本?

How to load a d3-dependent script using RequireJS?

我正在尝试使用 RequireJS 加载 d3-path。查看压缩后的 d3-path 源代码,它看起来符合 AMD 标准,因为我在第一行看到了这个:

!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?s(exports):"function"==typeof define&&define.amd?define(["exports"],s):s(t.d3=t.d3||{})}

我的index.html长得像

<script>
    require.config({
        paths: {
            "d3": "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min",
            "d3-path": "https://d3js.org/d3-path.v1.min",
            "underscore": "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min",
            "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"
        }
    });
</script>

我正在尝试加载的 JS 文件 d3.path() 看起来像

require([
    "d3",
    "d3-path",
    "underscore"
],
function(
    d3,
    d3_path,
    _
) {
    // d3, d3_path, and _ are defined
    // but d3.path() isn't defined 
});

我可以通过 d3_path.path() 使用 d3-path,但理想情况下我想 d3.path()。但是,如果我将 d3d3-path 都设置为 d3,那么 d3-path 会覆盖 d3,并且我会失去主要的 d3 功能。

我也对 RequireJS 最佳实践持开放态度,因为我不确定我是否使用了最佳方法。谢谢!

初步说明:您正在尝试使用 V4 模块加载 d3 V3,这不会很好地啮合。

关于您的问题:这就是您使用微模块时的预期工作方式。您加载孤立的功能并将它们组合起来。

当您使用 vanilla environments 时,您只会得到一个 d3 全局变量,如文档中所述:尝试

require.config({
    paths: {
        "d3": "https://d3js.org/d3.v4.min"
    }
});

require(['d3'], function(myd3) {
    console.log(window.d3); // undefined
    console.log(myd3); // d3 object
});

请注意,如果您加载整个 d3 v4 库,您将得到 d3.path :

require(['d3'], function(myd3) {
    console.log(myd3.path); // function
});

最后,如果你打算使用多个微模块,你可以使用映射配置:

require.config({
    paths: {
        d3src: 'https://d3js.org'
    },
    map: {
        '*': {
            'd3':  'd3src/d3.v4.min',
            'd3-selection':  'd3src/d3-selection.v1.min',
            'd3-path': 'd3src/d3-path.v1.min',
        }
    }
});


// if you want to load the selection and the path modules
require(['d3-selection', 'd3-path'], function(selection, path) {
    // ...
});

// if you want to load d3
require(['d3'], function(d3) {
    // ...
});

除了 nikoshr 关于使用 d3 微型库的回答:您应该以连字符样式命名 d3 模块,例如d3-selection,因为一些 d3 库依赖于其他库,并且 require 它们在此语法中。

此外,您可以在模块中创建自己的 d3 对象,这样您就不必更改代码并可以使用 d3.path().

require(['d3-selection', 'd3-path'], function(d3Selection, d3Path) {
    let d3 = Object.assign({}, d3Selection, d3Path);

    d3.path();
});