我这里有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”的方式有关
有人知道这是为什么发生的,我该如何解决。
答案 0 :(得分:3)
编译器会在this
函数内部将insertLinebreak()
的类型推断为类StackedChartCompoent
。但是,在type definitions中查看d3.select(node)
,您会发现它期望节点扩展defined的BaseType
export type BaseType = Element | EnterElement | Document | Window | null;
因为您的课程显然没有扩展此BaseType
,所以您得到了错误。
基本上有两种解决方法:
如果仅在一个地方需要insertLinebreak()
方法,即作为对.each()
的回调,则可以使其成为函数表达式,然后将其作为参数直接传递给{{ 1}}
.each()
之所以可行,是因为编译器现在知道该函数的单个入口点,并且可以推断出.each(function() {
let labels = d3.select(this); // works
// ...the original method's body
})
的类型,因为.each()
使用Function.prototype.call()
将this
绑定到节点。
但是请记住,您必须使用经典函数表达式来支持ES6箭头函数,因为那样会使this
再次指向其词法范围而不是节点。 / sub>
幸运的是,TypeScript本身内置了一种更惯用的方式。自version 2.0起,您可以提供伪造的this
parameter作为函数参数列表中的第一项。该参数告诉编译器this
在所述函数内部指的是什么。因此,您的代码可以重写为:
this
答案 1 :(得分:0)
如果仍然找不到解决方案,请尝试一下!!
private insertLinebreak(d,i,n){
//d is your data
//i is the current index
//n is the current node
let labels = d3.select(this); // won't work
let labels = d3.select(n[i]); // works
}
祝您编程愉快!!!