我在这里有stackbiltz- https: //stackblitz.com/edit/lable-line-break-vaszab ? file = src/app/app.component.ts
我在Angular应用中有一个d3条形图。
使用创建z轴刻度的函数将x轴标签分为两行
private insertLinebreak(d) {
let labels = d3.select(this);
let words = d;
console.log("Label:", labels.html());
labels.text('');
let index = words.indexOf(' ', words.indexOf(' ') + 1)
let title = words.substr(0, index)
let subtitle = words.substr(index + 1)
let tspantitle = labels.append('tspan').text(title)
let tspansubtitle = labels.append('tspan').text(subtitle)
tspantitle
.attr('x', 0)
.attr('dy', '15')
.attr('class', 'x-axis-title');
tspansubtitle
.attr('x', 0)
.attr('dy', '16')
.attr('class', 'x-axis-subtitle');
};
该函数使用“ this”选择调用函数的“ g”(但在d3中,我认为它选择了整个svg)
这段代码可以在stackblitz中工作,但是在我的实际代码中我得到了错误
Argument of type 'this' is not assignable to parameter of type 'BaseType'.
我知道这不是很有帮助
我认为这与Typescript及其处理“ this”的方式有关
有谁知道为什么发生这种情况以及我该如何解决。
编译器将this
您insertLinebreak()
函数内部的类型推断为类StackedChartCompoent
。纵观类型定义的d3.select(node)
,但是,你可以看到,它期望的节点来扩展BaseType
其被定义为
export type BaseType = Element | EnterElement | Document | Window | null;
因为您的课程显然没有扩展此内容,所以BaseType
您遇到了错误。
基本上有两种解决方法:
如果insertLinebreak()
仅在一个地方需要该方法,即作为的回调.each()
,则可以使其成为函数表达式,然后将其作为参数直接传递给.each()
.each(function() {
let labels = d3.select(this); // works
// ...the original method's body
})
这工作,因为编译器现在知道这个功能的单一入口点,并且可以推断出的类型this
,因为.each()
使用Function.prototype.call()
绑定this
到节点。
但是请记住,必须使用经典函数表达式来支持ES6箭头函数,因为这将this
再次指向其词法范围,而不是节点。
幸运的是,TypeScript本身内置了一种更惯用的方式。从2.0版开始,您可以在函数的参数列表中提供一个伪this
参数作为第一项。该参数告诉编译器this
该函数内部指的是什么。因此,您的代码可以重写为:
private insertLinebreak(this: SVGTextElement) {
let labels = d3.select(this); // works
// method body left untouched
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句