You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JS Class事件函数中引用构造函数的this?D3代码转类问题

解决D3类中事件监听函数访问实例this的问题

在D3的mouseover、mouseout这类事件回调里,默认this指向的是触发事件的DOM元素,而非你的类实例,所以直接用this.focusText会找不到对应属性。下面是几种实用的解决方法:

方法1:使用箭头函数

箭头函数不会绑定自身的this,会继承外层作用域的this(也就是类实例的this),直接就能访问类属性。

示例代码:

class MyChart {
  constructor(data) {
    this.focusText = d3.select('svg').append('text');
    this.circles = d3.select('svg').selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('r', 10)
      .attr('fill', 'black')
      // 箭头函数作为事件回调
      .on('mouseover', (event, d) => {
        // 这里的this就是类实例
        this.focusText.text(d.name).attr('x', event.clientX).attr('y', event.clientY);
        d3.select(event.currentTarget).attr('fill', 'red');
      })
      .on('mouseout', () => {
        this.focusText.text('');
        d3.select(event.currentTarget).attr('fill', 'black');
      });
  }
}

方法2:用bind绑定类实例的this

如果偏好使用普通函数作为回调,可以提前用bind把类实例的this绑定到回调函数上,确保回调里的this指向类实例。

示例代码:

class MyChart {
  constructor(data) {
    this.focusText = d3.select('svg').append('text');
    // 绑定this到类实例
    this.handleMouseOver = this.handleMouseOver.bind(this);
    this.handleMouseOut = this.handleMouseOut.bind(this);

    this.circles = d3.select('svg').selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('r', 10)
      .attr('fill', 'black')
      .on('mouseover', this.handleMouseOver)
      .on('mouseout', this.handleMouseOut);
  }

  handleMouseOver(event, d) {
    // 这里的this已经是类实例
    this.focusText.text(d.name).attr('x', event.clientX).attr('y', event.clientY);
    d3.select(event.currentTarget).attr('fill', 'red');
  }

  handleMouseOut(event) {
    this.focusText.text('');
    d3.select(event.currentTarget).attr('fill', 'black');
  }
}

方法3:在构造函数里保存实例this到变量

在构造函数里把类实例的this存到一个变量(比如self/that),回调里用这个变量访问类属性,同时不影响用this操作DOM元素。

示例代码:

class MyChart {
  constructor(data) {
    const self = this; // 保存类实例的this
    this.focusText = d3.select('svg').append('text');

    this.circles = d3.select('svg').selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('r', 10)
      .attr('fill', 'black')
      .on('mouseover', function(event, d) {
        // 用self访问类实例属性,this还是指向DOM元素
        self.focusText.text(d.name).attr('x', event.clientX).attr('y', event.clientY);
        d3.select(this).attr('fill', 'red');
      })
      .on('mouseout', function() {
        self.focusText.text('');
        d3.select(this).attr('fill', 'black');
      });
  }
}

补充:D3 v6+的事件处理注意点

从D3 v6开始,事件回调的第一个参数是event对象,第二个是数据d。如果需要操作触发事件的DOM元素,推荐用d3.select(event.currentTarget),不管用哪种this绑定方式都能正常获取元素。

内容的提问来源于stack exchange,提问作者smpa01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 06:10:01