A d3.select... эквивалентно jQuery.children()

Я использую d3 для добавления некоторых элементов в enter(), а затем обновляю их позже. Однако в следующий раз, когда я попытаюсь выбрать эти элементы, выбор намного больше, чем оригинал. Это связано с тем, что в исходных элементах выбора теперь есть дети, которые являются одинаковыми типами, например; <g>, <svg>. Я ожидал, что selectAll() будет работать только на первом децентрализованном уровне, например jQuery.children(), есть ли эквивалент в d3? Если не самый эффективный способ подделать это?

Ответ 1

Нет эквивалента jQuery.children(). Обычно это обрабатывается путем назначения выделяющего класса элементам, которые вы хотите выбрать вместе, например. что-то вроде этого.

svg.selectAll("g").data(data)
   .enter()
   .append("g")
   .attr("class", "parent")
   .append("g")
   .attr("class", "child");

svg.selectAll("g"); // all g elements
svg.selectAll("g.parent"); // only parents
svg.selectAll("g.child"); // only children

Ответ 2

Вот гораздо лучший способ сделать это:

var parent = d3.selectAll(".myParentClass");
parent.each(function(d,i) {            
   var children = d3.selectAll(this.childNodes);
   console.log(children);
});

Таким образом вам не нужно излишне добавлять классы к тому, что может быть 100 (или даже более) дочерних узлов.

Ответ 3

Вы также можете выбрать детей только с помощью селектора CSS. Вот что я делаю, чтобы выбрать child из индекса:

d3.select(`#${parentId} > *:nth-child(${index + 1})`)

поэтому я предполагаю, что это работает:

d3.selectAll(`#${parentId} > *`)

Ответ 4

Позднее стороне, но по крайней мере в d3 версии 4, selection.selectAll() может взять функцию, результатом которой является массив, который содержит новые элементы для выбора на основе выбранного элемента в предыдущем выборе:

var parent = d3.selectAll(".myParentClass");
var children = parent
    //Convert selection to selection representing the children
    .selectAll(function() { return this.childNodes; })
    //Apply filter to children
    .filter('g')
    ;

Основное преимущество этого подхода по сравнению с предыдущими ответами заключается в том, что функция selection.data() будет работать правильно. Ранее предложенные методы, которые назначают результаты из нового отдельного вызова d3.select(), не позволяют этого.

Ответ 5

Как говорит Ларс, в D3 нет эквивалента методу "children()", но здесь осталось небольшое расширение для прототипа d3.selection, который я написал. Надеюсь, вам помогут (так поздно).

d3.selection.prototype.children = function(d){
    var that = this.node();
    return this
        .selectAll(d)
        .filter(function(){ return that == this.parentNode; });
};