javascript - 将当前参数传递给循环中的函数
问题描述
我正在使用 D3 打印多个矩形。现在我希望矩形可以允许用户点击它并激活一些功能。
例如,有 3 个矩形"Tom"
,"Mary"
和"Ben"
。当用户点击不同的矩形时,它将传递当前值。就像我点击"Tom"
它时会传递"Tom"
调用该函数一样。
但是,我发现打印完矩形后,无论我点击哪个矩形,它们都返回数据集的最小值。
在我的示例中,即使我单击"Tom"
or "Mary"
,都返回"Ben"
。
for (var i = 0; i < ward_set.length; i++) {
var ward_id = ward_set[i];
legend.append("rect")
.attr("x", legend_x + 180 + 100 * n)
.attr("y", legend_y)
.attr("width", 18)
.attr("height", 18)
.attr("fill", colors[count])
.attr("class", "legend" + ward_set[i])
.on("click", function() {
console.log(ward_id);
});
}
解决方案
在编写 D3 代码时,您的问题完美地说明了一个非常重要的原则,一个经验法则,如果您愿意的话:永远不要使用循环来附加元素。请改用进入/更新/退出模式。
当您使用循环(无论是for
、等...)时会发生什么while
,forEach
不仅没有数据绑定,而且您还会遇到您所描述的这种奇怪的结果(始终获得最后一个值),此处对此进行了解释:JavaScript循环内的闭包——简单的实际例子
因此,使用 D3 惯用输入选择的解决方案将是:
const data = ["Tom", "Mary", "Ben"];
const svg = d3.select("svg");
const rects = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
//etc...
然后,在click
侦听器中,您得到第一个参数,即数据:
.on("click", function(d) {
console.log(d)
})
这是一个演示:
const data = ["Tom", "Mary", "Ben"];
const svg = d3.select("svg");
const rects = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.attr("width", 50)
.attr("height", 150)
.attr("x", (_, i) => i * 60)
.on("click", function(d) {
console.log(d)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>