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

3

我已经像这样在项目目录中安装了d3依赖项:

npm install d3 --save

我已经在组件中导入了d3模块,代码如下:

import d3 from "d3";

没有任何错误或警告提示。不幸的是,调用d3模块中的任何方法都会失败。

例如,我尝试绘制这个线状图表,但在该模块的第一个select方法处出现了错误。

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

这怎么可能?在VS Code上悬停在d3模块的每个方法上都会显示该方法的文档。因此,我猜测该模块不能是未定义的。

<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>

可能存在某些集成不匹配的问题,我自己无法解决。请帮忙。

1个回答

2

希望能知道您使用的是哪个版本的d3。我假设您正在使用最新的版本——目前为止是v6。

d3 v4仍然使用import d3 from 'd3';的导入方式,但在v6(和v5)中,现在使用ES模块的方式导入。

import * as d3 from 'd3';

这个变化使开发者可以选择他们需要的功能,编译器可以通过摇树优化依赖关系并只包含所需的功能。

因此,您也可以执行以下操作:

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

最终结果为较小的捆绑包


更新

错误:Uncaught (in promise) DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. 告诉你 d3.select(this.$el) 中的 $el 不是一个节点。 为了解决这个问题,请在 this.$nextTick(function () {...}) 内使用。

文档

mounted

Type: Function

**Details: **

Called after the instance has been mounted, where element, passed to app.mount is replaced by the newly created vm.$el. If the root instance is mounted to an in-document element, vm.$el will also be in-document when mounted is called.

Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted:

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

1
非常感谢您的回复,我已经安装了最新的d3版本,并选择了第一种方法import * as d3 from d3``,第二种方法被编译器立即拒绝。 然而,我仍然遇到错误。这次我收到了以下错误: Uncaught (in promise) DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. 您是否建议我使用更低版本的d3? - BWappsAndmore
这是因为在挂载时, this.$el 为 null 或未定义,你可能需要推迟到 $el 解析为 Node 后再执行。 - Daniel
非常感谢您的回复,很抱歉耽搁了(我休假了两天)。这似乎是一个错误。我无法让它正常工作。我将接受您的答案,因为我非常感激您的帮助。 - BWappsAndmore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接