12

我有一个d3.custom.build.js这样的文件(简化):

import { range } from 'd3-array';
import { select, selectAll, event } from 'd3-selection';
import { transition } from 'd3-transition';

export default {
    range,
    select,
    selectAll,
    event,
    transition
};

rollup.config.js这样:

import nodeResolve from 'rollup-plugin-node-resolve';

export default {
    entry: './js/vendor/d3-custom-build.js',
    dest: './js/vendor/d3-custom-built.js',
    format: 'iife',
    globals: {
        d3: 'd3'
    },
    moduleId: 'd3',
    moduleName: 'd3',
    plugins: [nodeResolve({ jsnext: true })]
};

我想导出到一个名为“d3”的普通旧浏览器全局。我从一个简单的 npm 脚本调用汇总。好消息是几乎所有东西都在输出文件中工作,除了一件事:d3.event在浏览器中总是为空。不,页面上的事件被劫持不是问题。当我将标准的完整 d3 4.0 库换成脚本标记时,一切正常。这绝对是构建问题。

d3 文档警告说捆绑event很棘手:

如果您使用 Babel、Webpack 或其他 ES6-to-ES5 捆绑器,请注意 d3.event 的值在事件期间会发生变化!d3.event 的导入必须是实时绑定,因此您可能需要将捆绑器配置为从 D3 的 ES6 模块而不是从生成的 UMD 包中导入;并不是所有的打包者都会遵守 jsnext:main。还要注意与 window.event 全局的冲突。

看来设置nodeResolve({ jsnext: true })是不够的。如何在捆绑包中获得实时绑定?非常感谢任何指导。

4

1 回答 1

14

您正在导出一个使用 ES2015 速记对象文字语法定义的对象,作为默认导出。这是您所写内容的长格式:

export default {
  range: range,
  select: select,
  selectAll: selectAll,
  event: event,
  transition: transition
}

因此,您的对象捕获了event加载时的值,该值为 null;它不是实时绑定,不会反映当前事件。

一种解决方法是event使用 getter 定义属性:

export default {
  range,
  select,
  selectAll,
  get event() { return event; },
  transition
}

最好使用命名导出而不是默认导出,然后汇总将自动生成实时绑定:

export {
  range,
  select,
  selectAll,
  event,
  transition
}

这不仅更短,而且现在您不再依赖支持 ES2015 速记对象文字语法的浏览器。

于 2016-10-14T16:51:18.340 回答