一般來說,直接導入整個d3,我們會這麼寫:
import * as d3 from 'd3';
這樣,我們就可以像在js裏一樣,使用熟悉的d3.select
了。
但是因爲不想一次性導入整個d3給項目增加大小,所以我就對d3進行了按模塊導入:
import * as d3 from 'd3-selection';
這個其實也不影響select,但是因爲我想給一個div增加transition的效果,就寫了這麼一段代碼:
div.transition()
.duration(500)
.style('opacity', 0.9);
這個看起來是沒啥問題的,但是使用的時候控制檯就會報錯div.transition() is not a function
。上網查了一下,有很多人說升級d3的版本,但是我用的是最新的5.x,而且transition方法是在d3-selection這個模塊裏的:
declare module 'd3-selection' {
interface Selection<GElement extends BaseType, Datum, PElement extends BaseType, PDatum> {
transition(name?: string): Transition<GElement, Datum, PElement, PDatum>;
}
}
找了很長時間,後來發現,事實上transition方法是通過d3-transition這個模塊掛載到selection上的,並不屬於d3-selection這個模塊本身。我們可以看看d3的源碼(省略了無關的部分):
// node_modules/d3-transition/src/selection/index.js
import {selection} from "d3-selection";
import selection_transition from "./transition.js";
selection.prototype.transition = selection_transition;
所以,如果直接導入d3-selection,是肯定找不到這個方法的。解決方案很簡單,就是添加一個依賴,導入這個包:
import * as d3 from 'd3-selection';
import 'd3-transition';
但是,爲什麼會有這種誤導呢,是d3寫錯了嗎?再仔細看看package.json:
"devDependencies": {
"@types/d3": "^5.7.2"
}
原因就在這裏了。因爲導入的是整個d3的類型聲明,他默認我已經導入了全部的依賴,所以纔會把transition方法放到Selection接口裏。如果我們看一下d3-selection模塊的類型聲明(node_modules/@types/d3-selection/index.d.ts
),就會發現,裏面並沒有transition方法。
所以,不僅僅在導入依賴的時候要正確導入,而且在node_modules裏的依賴也要正確。