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