简体   繁体   English

无法将 d3 集成到 Vue 3 组件中

[英]cannot integrate d3 into Vue 3 Component

I've installed the d3 dependency in the project directory like this:我已经在项目目录中安装了d3依赖项,如下所示:

npm install d3 --save

and I've imported the d3 module in the Component like this:我已经在Component中导入了d3模块,如下所示:

import d3 from "d3";

which shows no errors or warnings to me.这对我没有任何错误或警告。 Unfortunately, calling any method from the d3 module fails.不幸的是,从d3模块调用任何方法都会失败。

For example, I tried to draw this line chart and an error appeared at the very first select method from the module.例如,我尝试绘制折线图,模块的第一个select方法出现错误。

Uncaught (in promise) TypeError: Cannot read property 'select' of undefined.

How could this be?这怎么可能? Hovering on every single method of the d3 module in VS Code shows me the documentation of the method.将鼠标悬停在VS Coded3模块的每个方法上都会显示该方法的文档。 So I guess the module can't be undefined.所以我猜这个模块不能是未定义的。

<script>
import d3 from 'd3';
const data = [99, 71, 78, 25, 36, 92];
export default {
  name: 'non-vue-line-chart',
  template: '<div></div>',
  mounted() {
    const svg = d3.select(this.$el) // the error appears on the very first line of the d3-module
      .append('svg')
      .attr('width', 500)
      .attr('height', 270)
      .append('g')
      .attr('transform', 'translate(0, 10)');
    const x = d3.scaleLinear().range([0, 430]);
    const y = d3.scaleLinear().range([210, 0]);
    d3.axisLeft().scale(x);
    d3.axisTop().scale(y);
    x.domain(d3.extent(data, (d, i) => i));
    y.domain([0, d3.max(data, d => d)]);
    const createPath = d3.line()
      .x((d, i) => x(i))
      .y(d => y(d));
    svg.append('path').attr('d', createPath(data));
  },
};
</script>

There must be some integration mismatch, that I can't fix it by myself.一定有一些集成不匹配,我自己无法修复。 Please help.请帮忙。

Would be helpful to know which version of d3 you are using.知道您使用的是哪个版本的 d3 会很有帮助。 I'm going to assume it's the latest, which at this time is v6.我将假设它是最新的,此时是 v6。

d3 v4 still uses import d3 from 'd3'; d3 v4 仍然使用import d3 from 'd3'; way to import, but in v6 (and v5) the use ES modules now and way to do is.导入方式,但在 v6(和 v5)中,现在使用 ES 模块,方法是。

import * as d3 from 'd3';

This change allows the developer to select which features they need, and the compiler can then tree-shake the dependency and only include features needed.此更改允许开发人员对 select 进行他们需要的功能,然后编译器可以对依赖项进行树摇动,仅包含所需的功能。

So you could also do:所以你也可以这样做:

import {select, scaleLinear, axisLeft, axisTop, extent, max, line} as d3 from 'd3';

and end up with a smaller bundle最后得到一个更小的捆绑包


Update更新

The error: Uncaught (in promise) DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.错误: Uncaught (in promise) DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. is telling you that $el in d3.select(this.$el) is not a Node.告诉你d3.select(this.$el) $el的 $el 不是节点。 To resolve this, use inside this.$nextTick(function () {...})要解决此问题,请在this.$nextTick(function () {...})内部使用

docs 文档

mounted

Type: Function型号: Function

**Details: ** **细节: **

Called after the instance has been mounted, where element, passed to app.mount is replaced by the newly created vm.$el.在挂载实例后调用,其中传递给 app.mount 的元素被新创建的 vm.$el 替换。 If the root instance is mounted to an in-document element, vm.$el will also be in-document when mounted is called.如果根实例挂载到文档内元素,则调用 mount 时 vm.$el 也将在文档内。

Note that mounted does not guarantee that all child components have also been mounted.请注意,mounted 并不能保证所有子组件也已安装。 If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted:如果你想等到整个视图被渲染,你可以在mounted里面使用vm.$nextTick:

 mounted() { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM