ttm*_*tmt 1 d3.js typescript angular
我在这里有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');
};
Run Code Online (Sandbox Code Playgroud)
该函数使用“ this”选择调用函数的“ g”(但在d3中,我认为它选择了整个svg)
这段代码可以在stackblitz中工作,但是在我的实际代码中我得到了错误
Argument of type 'this' is not assignable to parameter of type 'BaseType'.
Run Code Online (Sandbox Code Playgroud)
我知道这不是很有帮助
我认为这与Typescript及其处理“ this”的方式有关
有谁知道为什么发生这种情况以及我该如何解决。
编译器将this您insertLinebreak()函数内部的类型推断为类StackedChartCompoent。纵观类型定义的d3.select(node),但是,你可以看到,它期望的节点来扩展BaseType其被定义为
export type BaseType = Element | EnterElement | Document | Window | null;
Run Code Online (Sandbox Code Playgroud)
因为您的课程显然没有扩展此内容,所以BaseType您遇到了错误。
基本上有两种解决方法:
如果insertLinebreak()仅在一个地方需要该方法,即作为的回调.each(),则可以使其成为函数表达式,然后将其作为参数直接传递给.each()
.each(function() {
let labels = d3.select(this); // works
// ...the original method's body
})
Run Code Online (Sandbox Code Playgroud)
这工作,因为编译器现在知道这个功能的单一入口点,并且可以推断出的类型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
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
663 次 |
| 最近记录: |