我有一个包装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已绑定到提供给on
的回调中(第3行)。还要注意,在function
上使用(...) => { ... }
-允许D3将this
绑定到它需要的对象。
如果我可以通过其他方式访问在this
中使用的D3对象,我很高兴在回调函数中失去d3.select(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)
})
})
}
答案 0 :(得分:2)
作为this
的替代方法,请尝试使用侦听器函数的第二个和第三个参数:
function(d,i,group) { d3.select(group[i] ... })
之所以行之有效,是因为使用selection.on("event",function(){})
或selection.each(function() {})
时,d3将当前元素绑定到this
上以提供所提供的功能。 D3还将三个参数绑定到所提供的函数:
d
)i
)group
)使用时:
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
的上下文。
答案 1 :(得分:1)
使用each
,map
等在cheerio上也会发生此错误。
TypeScript(>=2.0)
可以指定函数的这种类型。以下代码可以避免 TS2683 错误。
https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters
.on('mouseout', function(this: any, d: any) {
})