如何在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
相关产品推荐
相关产品推荐

