将 D3 代码转换为 Vue3 - 单元格不是添加到行而是添加到 HTML

Transforming D3 code into Vue3 - cells not being added to rows but into HTML

我找到了一个 GitHub version of Mike Bostock's adjacency matrix visualization,使用来自悲惨世界的数据。

我把它转换成Vue3代码,但由于这是我的第一个项目,我可能犯了一些错误。应添加到每一行的单元格已添加到主 HTML 并且未显示可视化(黑屏)。

这是转换后的 Vue3 格式可视化的在线版本: https://codesandbox.io/s/sweet-gould-dejiuj?file=/src/components/Miserables.vue:33765-33857

这是因为方法的上下文 roww() 不是正确的上下文。

使用以下代码创建一行:

const row = this.svg
  .selectAll(".row")
  .data(this.matrix)
  .enter()
  .append("g")
  .attr("class", "row")
  .attr("transform", (d, i) => `translate(0,${this.x(i)})`)
  .each(this.roww); 

选择的每个节点的最后一行调用 this.roww,但是该函数的上下文(this.roww 中的 this 关键字)以某种方式硬编码到它是一个对象的成员,因此它没有收到 should be the actual node object which relates to the DOM.

的正确上下文

要解决此问题,您需要使用使用 function 关键字创建的常规函数​​(出于与上述相同的原因而不是箭头函数),以便它可以传递正确的上下文,尽管由于您的函数精确地依赖于它的“父”上下文(另一个this),你必须在外部范围中设置一个引用它的变量,以便它可以在函数中读取:

// ...

const that = this;

function fillrow (row) {
  // eslint-disable-next-line no-unused-vars
  const cell = d3.select(this).selectAll(".cell")
    .data(row.filter((d) => d.z))
    .enter()
    .append("rect")
    .attr("class", "cell")
    .attr("x", (d) => that.x(d.x))
    .attr("width", that.x.bandwidth())
    .attr("height", that.x.bandwidth())
    .style("fill-opacity", (d) => that.z(d.z))
    .style("fill", (d) =>
      that.get_nodes[d.x].group === that.get_nodes[d.y].group
        ? that.c(that.get_nodes[d.x].group)
        : null
    )
    .on("mouseover", that.mouseover)
    .on("mouseout", that.mouseout);
}

const row = this.svg
  .selectAll(".row")
  .data(this.matrix)
  .enter()
  .append("g")
  .attr("class", "row")
  .attr("transform", (d, i) => `translate(0,${this.x(i)})`)
  .each(fillrow);

// ...