javascript - D3.js 在 "on"事件中丢失对象引用

标签 javascript d3.js

我需要一些帮助来理解我的小代码中发生的情况。在我的网络应用程序中,我使用 D3.js 绘制一些我称之为标记的形状。可以在屏幕上拖动标记,每次拖动时我都会确定其位置,进行一些计算并更新分配给该标记的数据对象。让我告诉你:

class Marker {
  constructor(name) {
    this.name = name;
    this.computedStuff = 0;
  }

  getDisplayName() {
    return 'Marker ' + this.name;
  }
}

this.markerValues = {
  'm1': new Marker('m1'),
  'm2': new Marker('m2')
}

this.svg.selectAll('g.marker')
        .data(_.values(this.markerValues))
        .join(enter => {
          const group = enter.append('g');

          group.append('path')
              .attr('d', 'M -12.867771,6.1070093 V 13.761566 H 12.867771 '
                  + 'V 6.1070093 H 6.4338855 '
                  + 'L 0,-1.1321257 -6.4338856,6.1070093 Z')
              .attr('transform', `translate(0 120) scale(2)`)
              .attr('stroke', 'black')
              .attr('stroke-width', '1px')
              .attr('fill', '#fff')
              .on('dblclick', d => console.log(d));

          group.append('text')
              .attr('y', 120)
              .text(d => d.getDisplayName())
              .style('font-size', '10px')
              .style('fill', 'black');

          return group;
        })
        .attr('class', 'marker')
        .call(d3.drag()
            .on('drag', function (d) {
              // Computation here

              d.computedStuff = computedAbove;

              // Here is a typical code for moving a marker according to 
              // d3.event.
            })
        );

问题出在:.on('dblclick', d => console.log(d));。这看起来非常简单——双击,记录数据内容;在我移动标记之前它“工作”得很好。移动标记时,compatedStuff 变量会因计算而更改,但随后双击路径会在控制台中记录旧值,就好像对象根本没有更改一样。我 100% 确定它已更改,因为我检查了 this.markerValues 对象的内容。事件处理程序看起来好像已附加了对象的副本,并且记录了该副本而不是原始对象。

但是...

当我从路径中删除此事件处理程序并将其附加到组时:group.on('dblclick', d => console.log(d));,然后它就可以工作了!我可以移动标记,双击它,并且始终会提供有效值。

为什么组处理程序始终提供有效数据,而附加到组子级的处理程序则保留某种副本或未引用的对象?

最佳答案

简单的解决方案是:不要使用粗箭头 .on('dblclick', d => console.log(d));

改用经典符号

.on('dblclick', function(d) { console.log(d) });

d3 设置处理程序中 this 的范围以引用所引用的节点。使用粗箭头会覆盖词法范围。

但是,如果您使用完整的处理程序签名并按索引引用当前节点,则可以在处理程序中使用粗箭头:

selection.on('dblclick', (d, i, nodes) => {
  console.log(nodes[i])
});

this article中有一个不错的解释

关于javascript - D3.js 在 "on"事件中丢失对象引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59930964/

相关文章:

javascript - d3js - 从 linearScale 刻度生成自定义标签

javascript - D3 力导向图中的 "Pinning"个节点

javascript - d3.js 散点图中 [0,0] 处的神秘数据点

javascript - D3 TreeMap 布局调整大小

javascript - d3 sankey 图表 - 沿 x 轴手动定位节点

javascript - 生成 DOM 元素时替代 JavaScript `with` 语句

javascript - 如何在输入标签上调用验证函数

javascript - 如何找出调用了哪个 Javascript 函数?

javascript - 需要 jsx 文件而不指定扩展名

javascript - 如何使表格中的整个 <tr> 像 <a href =""> 一样可点击