this
来获取被拖动事件的 DOM 元素:
当指定的事件被触发时,每个监听器都将使用与 selection.on 监听器相同的上下文和参数进行调用:当前数据 d 和索引 i,this 上下文为当前的 DOM 元素。
但是我的回调函数是一个对象实例,this
指向该对象。因此我需要另一种获取通常由 this
传递的当前 DOM 元素的方法。我该怎么做?
this
来获取被拖动事件的 DOM 元素:
当指定的事件被触发时,每个监听器都将使用与 selection.on 监听器相同的上下文和参数进行调用:当前数据 d 和索引 i,this 上下文为当前的 DOM 元素。
但是我的回调函数是一个对象实例,this
指向该对象。因此我需要另一种获取通常由 this
传递的当前 DOM 元素的方法。我该怎么做?
使用第二个和第三个参数一起来获取this
当this
不可用时:
d3.drag().on(typename, function(d, i, n) {
//here, 'this' is simply n[i]
})
为了详细说明,可以查看下面我写的关于箭头函数中this
的处理文章。虽然问题不同,但解释是一样的。
这里有一个基本演示,请尝试拖动圆圈并查看控制台:
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:因为在 Stack Snippets 中尝试对 D3 selection 进行 console.log 会导致冻结,所以我在 D3 selection 上使用了 JSON.stringify
。
箭头函数中使用 "this"
D3.js 中的大多数函数都接受一个匿名函数作为参数。常见的示例包括 .attr
, .style
, .text
, .on
和 .data
,但是列表远不止这些。
在这种情况下,匿名函数将依次针对每个选定的元素进行评估,并传递:
d
)i
)nodes
)this
作为当前 DOM 元素。datum、index 和 current group 都作为参数传递,这是 D3.js 中著名的第一个、第二个和第三个参数(在 D3 v3.x 中,它们的参数通常被命名为 d
、i
和 p
)。然而,为了使用 this
,不需要使用任何参数:
.on("mouseover", function(){
d3.select(this);
});
当鼠标悬停在元素上方时,上述代码将选择this
。可以在此fiddle中检查其工作情况:https://jsfiddle.net/y5fwgopx/
作为新的ES6语法,箭头函数与函数表达式相比具有更短的语法。然而,对于一个经常使用this
的D3程序员来说,它存在一个陷阱:箭头函数不会创建自己的this
上下文。这意味着,在箭头函数中,this
具有其来自封闭上下文的原始含义。
这在几种情况下可能很有用,但对于习惯于在D3中使用this
的编码人员来说,这是一个问题。例如,使用上面的fiddle中的相同示例,以下代码将不起作用:
.on("mouseover", ()=>{
d3.select(this);
});
如果您怀疑,这里有一个示例:https://jsfiddle.net/tfxLsv9u/
这并不是大问题:需要时可以使用常规的函数表达式。但是如果要编写所有代码均使用箭头函数呢?是否可能在 D3 中使用箭头函数并仍正确地使用 this
?
答案是肯定的,因为 this
相当于 nodes[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", ()=>{d3.select(d3.event.target);})
。这段代码的作用是在鼠标悬停时选择d3事件的目标元素。 - Gerardo Furtado