当 `this` 不可用时,从拖动回调中检索 DOM 目标

Posted

技术标签:

【中文标题】当 `this` 不可用时,从拖动回调中检索 DOM 目标【英文标题】:Retrieve DOM target from drag callback when `this` is not available 【发布时间】:2017-12-28 22:51:25 【问题描述】:

d3.drag 的文档指出,拖动事件的 DOM 元素目标将在 this 中提供给回调:

当指定事件被调度时,每个侦听器将被调用,其上下文和参数与 selection.on 侦听器相同:当前数据 d 和索引 i,其中 this 上下文作为当前 DOM 元素。

但我的回调是一个对象实例,this 指向该对象。所以我需要另一种方式来访问通常在this 中传递的当前DOM 元素。我该怎么做?

【问题讨论】:

【参考方案1】:

this不可用时,将第二个和第三个参数一起使用得到this

d3.drag().on(typename, function(d, i, n) 
  //here, 'this' is simply n[i]
)

详细解释请看下面我写的在箭头函数中处理this的文章。这个问题和你的不同,但解释是一样的。

这里是一个基本的demo,试着拖个圈看看控制台:

var data = d3.range(5)
var svg = d3.select("body")
  .append("svg")
  .attr("width", 400)
  .attr("height", 100);
var circle = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d) 
    return 50 + 50 * d
  )
  .attr("r", 10)
  .attr("fill", "tan")
  .attr("stroke", "black")
  .call(d3.drag()
    .on("start", function(d, i, n) 
      console.log(JSON.stringify(n[i]))
    ))
<script src="https://d3js.org/d3.v4.min.js"></script>

PS:我在 D3 选择上使用JSON.stringify,因为如果您尝试控制台记录 D3 选择,堆栈 sn-ps 会冻结。


将“this”与箭头函数一起使用

D3.js 中的大多数函数都接受匿名函数作为参数。常见的例子有.attr.style.text.on.data,但列表远不止这些。

在这种情况下,匿名函数会按顺序对每个选定的元素进行评估:

    当前数据 (d) 当前索引 (i) 当前组 (nodes) this 作为当前 DOM 元素。

数据、索引和当前组作为参数传递,即 D3.js 中著名的第一个、第二个和第三个参数(其参数在 D3 v3.3 中传统上命名为 dip。 X)。但是,对于使用this,不需要使用任何参数:

.on("mouseover", function()
    d3.select(this);
);

当鼠标悬停在元素上时,上面的代码将选择this。检查它在这个小提琴中的工作:https://jsfiddle.net/y5fwgopx/

箭头函数

作为一种新的 ES6 语法,与函数表达式相比,箭头函数的语法更短。但是,对于经常使用this 的 D3 程序员来说,存在一个陷阱:箭头函数不会创建自己的 this 上下文。这意味着,在箭头函数中,this 的原始含义来自封闭的上下文。

这在多种情况下可能很有用,但对于习惯于在 D3 中使用this 的程序员来说,这是一个问题。例如,使用上面小提琴中的相同示例,这将不起作用:

.on("mouseover", ()=>
    d3.select(this);
);

如果你怀疑,这里是小提琴:https://jsfiddle.net/tfxLsv9u/

嗯,这不是什么大问题:可以在需要时简单地使用常规的老式函数表达式。但是,如果您想使用箭头函数编写所有代码怎么办?是否有可能有一个带有箭头函数的代码并且仍然可以在 D3 中正确使用this

第二个和第三个参数组合

答案是是的,因为thisnodes[i] 相同。提示实际上存在于整个 D3 API 中,当它描述时:

...this 作为当前 DOM 元素 (nodes[i])

解释很简单:因为nodes是DOM中的当前元素组,i是每个元素的索引,nodes[i]指的是当前DOM元素本身。即this

因此,可以使用:

.on("mouseover", (d, i, nodes) => 
    d3.select(nodes[i]);
);

这是对应的小提琴:https://jsfiddle.net/2p2ux38s/

【讨论】:

.on("mouseover", (d, i, nodes) => d3.select(nodes[i]); );这在 d3 V4 中可用我们如何在 d3 v3 中做到这一点 @AjinkyaDhote 这样做:.on("mouseover",()=>d3.select(d3.event.target);) 我尝试了 jsfiddle。它给出了我现在得到的相同错误。可能是因为版本变化什么的 @krishna 好吧,这不是投反对票的理由,因为我在这里的回答显然是正确的:你做错了其他事情。如果你有问题,我建议你发布一个问题来重现它。

以上是关于当 `this` 不可用时,从拖动回调中检索 DOM 目标的主要内容,如果未能解决你的问题,请参考以下文章

当静态库不可用时,是不是可以从 linux 交叉编译 Windows?

当目的地不可用时如何停止使用骆驼路线中的消息

Android WifiP2p - 当发现的设备不可用时收到通知

当锁定不可用时,调用Lock.lock()的线程何时从调用返回?

如何修复 PWA 审核中的“当 JavaScript 不可用时不提供后备内容”?

当 uibiquity 容器 (iCloud) 不可用时存储 UIManagedDocuments