【问题标题】:Import a package as an extension of another package with ES6 syntax使用 ES6 语法导入一个包作为另一个包的扩展
【发布时间】:2021-08-14 11:12:49
【问题描述】:

为了在 D3 中扩展地图投影,建议需要这样的包:

const d3 = require("d3")
require("d3-geo-projection")(d3)

这样,您可以使用父包中的 d3-geo-projectiongeoAiry 方法:

d3.geoAiry()

使用import 我正在这样做:

import * as d3 from 'd3'
import * as d3geo from 'd3-geo-projection'

然后方法不统一:

d3.geoMercator()
d3geo.geoAiry()

我试过了,但它不起作用:

import * as d3 from 'd3'
import * as d3geo from 'd3-geo-projection'
d3geo(d3)

那么,简而言之,ES6 语法中 require("d3-geo-projection")(d3) 的等价物是什么?

【问题讨论】:

  • 分别导入d3d3geo没有错。他们的统一是什么意思?
  • 你试过import d3 from 'd3'; import d3geo from 'd3-geo-projection'; d3geo(d3); 吗? import * as d3geo from ... 将始终使 d3geo 成为对象,因此您不能调用它。您确实需要研究 d3 如何导出其值。
  • Object.assign(d3, d3geo) 应该可以完成这项工作。
  • Mike Bostock 对如何导入这些模块有自己的看法:github.com/d3/d3-geo-projection/issues/128
  • @FelixKling 是的,马上就可以了。

标签: javascript npm d3.js ecmascript-6 import


【解决方案1】:

从技术上讲,您可以使用 d3.assign() 将所有属性从一个导入复制到另一个导入,松散地说。

import * as d3 from 'd3';
import * as d3geo from 'd3-geo-projection';

Object.assign(d3, d3geo);

这将使您的所有属性在您要求的 d3 对象下可用:

d3.geoMercator()
d3.geoAiry()
// ...

但是,你应该那样做吗?在我看来,您应该避免将两个导入聚合到一个对象中。这似乎是许多开发人员屈服于 ES6 之前的一些反射,因为他们被教导这样做是为了通过将代码汇总到对象中来确保封装。不过,随着模块的引入,JS 中封装的概念略有改变。

Mike Bostok 本人对他在 GitHub issue 的回答中所描述的问题有自己的看法,该问题正是您发布的问题。他鼓励完全放弃使用import * as d3,而只导入您实际要使用的模块的那些部分。就个人而言,我支持该建议,因为我认为这是为了清晰和简洁而在现代 JS 代码中使用模块的方式。我愿意为自己的代码接受的唯一例外是从单个模块中使用大量(例如 20 多个)导出成员,尽管这也可能表明一些代码异味,建议您应该考虑重构自己的模块把它分解成更小的部分。

为了更加模块化,我通常更喜欢使用单个模块,而不是看起来像这样的整个 d3 包:

import { select, selectAll } from "d3-selection";
import { min, max } from "d3-array";
import { geoAiry } from "d3-geo-projection";
// ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2015-08-23
    • 2019-11-08
    • 2018-03-20
    • 2020-02-24
    • 1970-01-01
    • 2015-09-27
    相关资源
    最近更新 更多