检查d3.select或d3.selectAll

时间:2017-08-14 21:03:43

标签: d3.js

我在可重复使用的图表上有一个方法可以传递一个选择,如果传递了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
}

1 个答案:

答案 0 :(得分:2)

好吧,有时在S.O.的问题根本没有答案(它有happened before)。

这似乎是你的这个问题:“是否有一种更为内在的方法来确定选择是来自select还是selectAll?”。可能没有。

为了证明这一点,让我们看一下d3.selectd3.selectAll的源代码(重要:那些不是 selection.selectselection.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);
}

正如您所看到的,我们在这里只有两个差异:

  1. d3.selectAll接受null。那对你没有帮助。
  2. d3.selectAll使用querySelectorAll,而d3.select使用querySelector
  3. 第二个差异是唯一适合你的,正如你现在所知,自querySelectorAll以来:

      

    返回与指定的选择器组匹配的文档中的元素列表(使用文档节点的深度优先预先遍历遍历)。返回的对象是 NodeList 。 (强调我的)

    querySelector仅...:

      

    返回文档中与指定选择器或选择器组匹配的第一个元素。

    因此,您现在正在使用的未记录的(和hacky,因为您正在使用_groups,这不是一个好主意)selection._groups[0] instanceof NodeList似乎是告诉选择创建的唯一方法来自d3.select创建的选择的d3.selectAll