我在可重复使用的图表上有一个方法可以传递一个选择,如果传递了d3.select('#id')
选择,则返回一个值,如果传递了d3.selectAll('.class')
选择,则返回一个值数组。我目前正在使用context._groups[0] instanceof NodeList
查询传递的参数,但使用未记录的属性感觉有点脆弱,因为在将来的版本中可能会有所改变。是否有更内置的方法来确定选择是来自select
还是selectAll
?
selection.size()
在这里没有帮助,因为它只告诉我们选择的结果,而不是它的调用方式。
编辑: 这是使用的背景。我正在使用Mike Bostock的reusable chart pattern,这个实例包含了获取/设置甜甜圈标签的方法。
对我而言,此API使用遵循principle of least astonishment,因为我希望返回结果。
var donut = APP.rotatingDonut();
// set label for one element
d3.select('#donut1.donut')
.call(donut.label, 'Donut 1')
d3.select('#donut2.donut')
.call(donut.label, 'Donut 2')
// set label for multiple elements
d3.selectAll('.donut.group-1')
.call(donut.label, 'Group 1 Donuts')
// get label for one donut
var donutOneLabel = d3.select('#donut1').call(donut.label)
// donutOnelabel === 'Donut 1'
// get label for multiple donuts
var donutLables = d3.selectAll('.donut').call(donut.label)
// donutLabels === ['Donut 1', 'Donut 2', 'Group 1 Donuts', 'Group 1 Donuts']
和内部方法定义:
App.rotatingDonut = function() {
var label = d3.local();
function donut() {}
donut.label = function(context, value) {
var returnArray;
var isList = context._groups[0] instanceof NodeList;
if (typeof value === 'undefined' ) {
// getter
returnArray = context.nodes()
.map(function (node) {return label.get(node);});
return isList ? returnArray : returnArray[0];
}
// settter
context.each(function() {label.set(this, value);});
// allows method chaining
return donut;
};
return donut
}
答案 0 :(得分:2)
好吧,有时在S.O.的问题根本没有答案(它有happened before)。
这似乎是你的这个问题:“是否有一种更为内在的方法来确定选择是来自select还是selectAll?”。可能没有。
为了证明这一点,让我们看一下d3.select
和d3.selectAll
的源代码(重要:那些不是 selection.select
和selection.selectAll
,它们彼此非常不同。)
首先,d3.select:
export default function(selector) {
return typeof selector === "string"
? new Selection([[document.querySelector(selector)]], [document.documentElement])
: new Selection([[selector]], root);
}
现在,d3.selectAll:
export default function(selector) {
return typeof selector === "string"
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
: new Selection([selector == null ? [] : selector], root);
}
正如您所看到的,我们在这里只有两个差异:
d3.selectAll
接受null
。那对你没有帮助。d3.selectAll
使用querySelectorAll
,而d3.select
使用querySelector
。第二个差异是唯一适合你的,正如你现在所知,自querySelectorAll以来:
返回与指定的选择器组匹配的文档中的元素列表(使用文档节点的深度优先预先遍历遍历)。返回的对象是 NodeList 。 (强调我的)
querySelector仅...:
返回文档中与指定选择器或选择器组匹配的第一个元素。
因此,您现在正在使用的未记录的(和hacky,因为您正在使用_groups
,这不是一个好主意)selection._groups[0] instanceof NodeList
似乎是告诉选择创建的唯一方法来自d3.select
创建的选择的d3.selectAll
。