我正在尝试向图表中的栏添加一个事件。我尝试了这个function
,但是使用此功能,无论我点击哪个栏,它总是会返回key
中的最后一个array
。
我的猜测是这与异步有关,因为它返回最后的key
值。
for (var key in data) {
bar = bars.append('rect')
.attr('class', 'bar')
.attr('x', (dimensions.width / data.length) * currentId + 41)
.attr('y', 100 - data[key] + 10).attr('height', data[key])
.attr('width', dimensions.width / data.length)
.attr('fill', '#4682B4')
.on('click', (bar = key) => {
console.log(key) //Always returns the same key
});
currentId++;
}
我还尝试复制数组中包含的一个键,然后创建一个if语句:
console.log(key === 1 ? true : false);
这将完全按照原样返回true
和false
。我认为这与async
有关的另一个原因。
我的基本问题是;
如何在此栏上点击活动,返回正确的key
答案 0 :(得分:2)
在此之前:这是不在D3中添加事件的惯用方式。作为一般规则,当您编写D3代码时,通常不需要任何类型的循环。当然,我们有时使用循环,但在非常特定的情况下,并解决非常具体的问题。因此,D3代码中找到的98.57%的循环是不必要的(来源:FakeData Inc.),无论是for...in
,for...of
还是简单的for
循环。
话虽如此,让我们看看这里发生了什么。
您的真正问题与D3或异步代码无关。实际上,你可以通过这个出色的答案来解释你的问题:JavaScript closure inside loops – simple practical example(我会避免将其作为副本关闭)。
在阅读上面链接中的答案后,让我们看看两个演示。
第一个,使用var
。请点击圈子:
var data = [{
name: "foo",
value: 1
}, {
name: "bar",
value: 2
}, {
name: "baz",
value: 3
}];
var svg = d3.select("svg");
for (var key in data) {
var foo = key;//look at the var here
circle = svg.append("circle")
.attr("cy", 50)
.attr("fill", "teal")
.attr("cx", d=> 20 + key*50)
.attr("r", 15)
.on('click', () => {
console.log(foo)
});
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
现在另一个,使用let
,请点击圈子并比较结果:
var data = [{
name: "foo",
value: 1
}, {
name: "bar",
value: 2
}, {
name: "baz",
value: 3
}];
var svg = d3.select("svg");
for (var key in data) {
let foo = key;//look at the let here
circle = svg.append("circle")
.attr("cy", 50)
.attr("fill", "teal")
.attr("cx", d=> 20 + key*50)
.attr("r", 15)
.on('click', () => {
console.log(foo)
});
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;