Mike 有一篇关于在 D3 中编写可重用组件的优秀文章。本文描述了如何使组件可配置以及如何将组件应用于选择的模式。
该模式允许通过将单个组件对象连接到数据来重复使用多个选择;例如
var chart = myChart();
d3.select("div.chart")
.data(data)
.call(chart);
我的组件实现如下所示:
function myChart() {
function my(selection) {
selection.each(function(d, i) {
// generate chart here
// `d` is the data, `i` is the index, `this` is the element
var state = false;
var circle = d3.select(this).append("circle")
.attr("r", "10")
.style("fill", "#000")
.on("click", toggleState);
function toggleState() {
// this function updates the current instance trapped by this closure
(state = !state)
? circle.style("fill", "#fff")
: circle.style("fill", "#000");
}
});
}
my.toggleState(i) {
// How do I access the `i`th instance of the component here?
}
return my;
}
我想要实现的是允许调用者在给定索引的情况下操作该组件的实例。例如,如果div.chart
上面的选择器返回一个包含两个元素的选择,我想调用chart.toggleState(1)
并让它更新选择中的第二个 div。
只是为了不让任何人混淆我为什么要这样做,调用者需要将两种类型的组件同步在一起。想象一下,我有一个由圆形表示的组件和另一个由矩形表示的组件。这两个组件必须是独立的,不能相互捆绑。我需要能够创建 4 个圆和 4 个矩形,当我单击一个矩形时,我希望能够根据索引顺序更新相应的圆。我已经想出了如何从组件中引发事件(d3.dispatch)并提供当前索引作为事件中的参数,但我还没有想出如何在给定索引的情况下调用组件的特定实例。