javascript - D3回调函数的 `this`阴影对象的 `this`

标签 javascript typescript d3.js

我有一个包装 D3 的类。我正在将其转换为 TypeScript,但遇到以下两个错误,并且不知道如何修复它们(实际上有多个错误,但它们都与这一对类似),

src/d3-graph.ts:295:19 - error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. 
295         d3.select(this)
                      ~~~~

  src/d3-graph.ts:294:23
    294       .on('mouseout', function(d: any) {
                              ~~~~~~~~
    An outer value of 'this' is shadowed by this container.

代码(类内的方法,添加行号以供引用),

...
1 private _enableNodeHighlightOnHover() {
2   this._nodes
3     .on('mouseout', function(d: any) {
4       d3.select(this)
5         .style('stroke-width', '2px')
6     })
7 }
...

注意第 2 行,this 指的是该类的实例对象。

在第 4 行,this 引用了对象 D3,该对象已绑定(bind)到提供给 on(第 3 行)的回调函数上。另请注意在 (...) => { ... } 上使用 function ——以允许 D3 将 this 绑定(bind)到它需要的对象。

如果我可以访问在 d3.select(this) 中使用的 D3 对象,我非常乐意在回调函数中失去 this 用法以其他方式。但我不确定那会是什么。

还需要适应此模式的其他用途,

private _enableDrag() {
  const that = this

  this._drag = d3.drag()
  this._drag
    .on('drag', function(d: any) {
      d.x += d3.event.dx
      d.y += d3.event.dy

      d3.select(this)
        .attr('cx', d.x)
        .attr('cy', d.y)

      that._links.each(function(l: any) {
        if (l.source === d.id)
          d3.select(this)
            .attr('x1', d.x)
            .attr('y1', d.y)
        else if (l.target === d.id)
          d3.select(this)
            .attr('x2', d.x)
            .attr('y2', d.y)
      })

      if (that._nodeTextLabels === null)
        logger.warn(
          'enableDrag called before this._nodeTextLabels has been initialized')
      else
        that._nodeTextLabels.each(function(n: any) {
          if (n.id == d.id)
            d3.select(this)
              .attr('x', d.x + D3Graph._LABEL_FONT_SIZE / 2)
              .attr('y', d.y + 15)
        })

      that._nodes.each(function(n: any) {
        if (n.id == d.id)
          d3.select(this).select('circle')
            .attr('cx', d.x)
            .attr('cy', d.y)
      })
    })
}

最佳答案

作为 this 的替代方案,尝试使用监听器函数的第二个和第三个参数:

  function(d,i,group) { d3.select(group[i] ... })

这是有效的,因为当使用 selection.on("event",function(){})selection.each(function() {}) 时,d3 绑定(bind)所提供函数的当前元素到 this 。 D3 还将三个参数绑定(bind)到提供的函数:

  • 当前数据 (d)
  • 当前索引 (i)
  • 选择中的元素组,而不是选择的元素(此处名为)

使用时:

selection.on("event", function() { d3.select(this); })

您实际上正在做同样的事情:

selection.on("event", function(d,i,group) { d3.select(group[i]); })

由于 group 保存选择的元素,并且 i 是当前索引,因此 group[i] 是当前元素,即与this相同。

使用group[i]允许使用箭头函数和环境,这些函数和环境可能会改变this的上下文,同时仍然访问当前元素。

关于javascript - D3回调函数的 `this`阴影对象的 `this`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53839100/

相关文章:

javascript - 如果要添加的元素已存在于列表中,则 jQuery appendTo 会替换元素而不是添加它们

javascript - 根据用户输入替换而不是附加?

node.js - TypeScript 内存错误未终止 Docker 构建

d3.js - 如何在 d3.js 中并排对齐两个 svg

javascript - 如何在 d3 散点图上剪裁趋势线?

javascript - 使用 jQuery 检测表单输入的自动完成

javascript - 将数组的最后一个元素复制到不同的位置,然后从数组的末尾删除它

typescript - 如何从emitDeclarationOnly获取TS编译器错误?

javascript - 自定义表单控件 (ControlValueAccessor) 的绑定(bind) ngModel 总是将表单设置为脏状态

javascript - D3 中 Force Layout 的分层边缘捆绑