如何将 D3 JavaScript 中的“this”翻译成 TypeScript?

Posted

技术标签:

【中文标题】如何将 D3 JavaScript 中的“this”翻译成 TypeScript?【英文标题】:How to translate 'this' in D3 JavaScript to TypeScript? 【发布时间】:2017-09-18 21:49:06 【问题描述】:

根据这篇文章'this' in TypeScript,我知道 javascript 中的“this”与 TypeScript 中的含义不同。我在 JavaScript 中有以下代码,用于在所选节点上创建较粗的笔划,并为所有其他节点提供较小的笔划。

node.on('click', function (d) 
   d3.selectAll('circle').attr('stroke-width', 1.5);
   d3.select(this).select('circle').attr('stroke-width', 5);
)

在 TypeScript 中我有

this.node.on('click', (d:any) => 
   this.node.selectAll('circle').attr('stroke-width', 1.5);
   [this is where I need help].select('circle').attr('stroke-width', 5);

【问题讨论】:

你为什么想要它?用第一个sn-p就可以了,不需要箭头函数语法。 因为 'this' 在 JavaScript 中的含义与在 TypeScript 中的含义不同,我正在尝试为 Angular 2 应用程序找到实现 JavaScript 代码的“正确”方法。跨度> this 在 TS 和 JS 中的行为具有完全相同的含义。看到更多代码会很有趣。奇怪的是,您同时使用this.node 作为d3node 的替代品。你的情况正确吗? @H.Trujillo 那篇文章不是这么说的。它表示在 JavaScript 以及 TypeScript 中,this 的行为与 其他 语言不同。 @dfsq 不幸的是,仅使用 d 对象(第一个参数)无法获取 DOM 元素。但是,第二个和第三个参数可以很容易地用于获取this(在 D3 方法中是当前的 DOM 元素)。 【参考方案1】:

正如this comment 和this answer 中所述,this 在 JavaScript 和 TypeScript 之间有不同的含义。

话虽如此,您的问题更简单:您试图在箭头函数中使用this 来获取当前的DOM 元素,但这根本行不通。

所以,简而言之,这里的问题是箭头函数和常规函数之间this 的区别,而不是 TypeScript 和 JavaScript 之间的区别。

解决方案

this 的替代方案在 API 中到处都有描述:当您在大多数 D3 方法中使用匿名函数时,传递的参数是...

...当前数据 (d)、当前索引 (i) 和当前组 (nodes),this 作为当前 DOM 元素 (nodes[i])。

因此,this 只是节点组(第三个参数)的当前索引(第二个参数)。

所以,在下面的sn-p中:

selection.on("foo", function (d, i, n)
    console.log(this)
    console.log(n[i])
)

两个console.log 将返回相同的东西。

当您使用箭头函数时,解决方案是(在 JavaScript 中):

this.nodes.on("click", (d, i, n) => 
    d3.select(n[i])//rest of your code here
)

如果您想详细了解如何使用第二个和第三个参数来获取 DOM 元素,请查看以下示例:d3 v4 retrieve drag DOM target from drag callback when `this` is not available

【讨论】:

不管这在 JavaScript 和 TypeScrip 之间有什么不同(我对此表示怀疑) 我只想说你怀疑是正确的。 OP 中的声明是 100% 错误的。他们的行为之间没有区别。 @AluanHaddad 谢谢你这么说。因为我从未使用过 TypeScript,所以我不想肯定地说任何话,但是是的,因为 TypeScript 编译为纯 JavaScript,这种说法毫无意义。 对它实际上并没有太多关于它编译成 JavaScript。例如 Dart 也是如此,但 Dart 确实以不同的方式对待 this。它是关于 TypeScript 是 JavaScript 的超集。这就是语言的定义。这意味着所有 JavaScript 构造都具有相同的含义,不是在编译输出中,而是在源代码级别。【参考方案2】:

这个问题的前提,如何将 D3 JavaScript 中的 'this' 翻译成 TypeScript?,是错误的。我没有投反对票,因为教育很重要。

我只想澄清this 在 TypeScript 和 JavaScript 中是 100% 相同的

事实上,all TypeScript 语法也是有效的 JavaScript 语法,具有 exact 相同的语义。

这就是使 TypeScript 成为 JavaScript 超集的原因。

更新:我实际上会修改这个答案,因为问题是你认为含义不同。你对箭头函数语法感到困惑

(params) => expression or block

首先=> 不是 TypeScript 功能,而是 JavaScript 功能。

其次,如上所述,TypeScript 自然支持这两种形式。这意味着不需要翻译。

this 在 TypeScript 中的含义与在 JavaScript 中的含义相同。

在这两种语言中,它在=> 的上下文中的含义与在function 的上下文中的含义不同。 SO上有很多很多解释这个的答案,所以我不会重复。

这就是这个问题的答案。

如果你有这个文件:

d3-app.js

node.on('click', function (d) 
  d3.selectAll('circle').attr('stroke-width', 1.5);
  d3.select(this).select('circle').attr('stroke-width', 5);
);

它可以工作,你想用 TypeScript 重写它。

这是你要做的:

    d3-app.js 重命名为 d3-app.ts

就是这样。

【讨论】:

【参考方案3】:

答案是将“this”替换为“d3.event.currentTarget”

d3.select(d3.event.currentTarget).select('circle').attr('stroke-width', 5);

【讨论】:

看我的回答,我解释了如何在 TypeScript 中“重写”它 其实看@GerardoFurtado的回答,他有更多的d3知识。

以上是关于如何将 D3 JavaScript 中的“this”翻译成 TypeScript?的主要内容,如果未能解决你的问题,请参考以下文章

如何引用 Vue 组件的 this 而不是 D3 的 this 实例

在 d3 javascript 中的圆形对象内添加图像?

如何确保 D3 在 javascript 运行之前完成加载多个 CSV?

d3 javascript中的变量范围

D3 中的鼠标位置

使D3堆积条形图填充父SVG容器