Предположим, у нас есть элемент svg без дочерних узлов:
<svg id = "bargraph" width = "400" height = "90" ></svg>
Предположим, у нас также есть массив данные:
var data = [10,20,30,40,50];
Этот код правильно добавляет новые элементы rect к элементу svg.
d3.select("#bargraph")
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("height", 10)
.attr("width", function(d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * 20; })
.attr("fill", "blue");
Код ниже не добавляет новые элементы rect к элементу svg. Ты можешь сказать мне, почему?
d3.selectAll("#bargraph rect")
.data(data)
.enter()
.append("rect")
.attr("height", 10)
.attr("width", function(d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * 20; })
.attr("fill", "blue");





Каждый раз, когда вы добавляете элементы, D3 добавляет их к выбранному родительскому элементу (ам). Вы не выбираете родительский элемент, вместо этого вы выбираете только те элементы, у которых есть указанный родительский элемент.
В вашем примере вы выбираете все rect, у которых есть родительский элемент с идентификатором bargraph, в то время как вы можете успешно обновить эти узлы с помощью:
d3.selectAll(#bargraph rect).data(data).attr(...)
Но использование следующего не добавит элементы в #bargraph (как вы утверждаете):
d3.selectAll("#bargraph rect).data(data).enter()
Здесь D3 просканирует весь документ, родительский элемент (d3.selectAll()) и вернет каждый соответствующий элемент, который соответствует критериям селектора. Выбор ввода затем создаст узел-заполнитель для каждого элемента в массиве данных, который не существует. Эти узлы создаются относительно выбора родительского элемента:
Conceptually, the enter selection’s placeholders are pointers to the parent element (documentation)
Так же, как мы можем выбирать прямоугольники и вводить круги, нет ничего, что связывает селектор и тип / размещение элемента, который мы хотим ввести.
В приведенном ниже примере я выбираю (и обновляю) круг SVG с помощью d3.selectAll("svg circle"), но я ввожу div - и мы видим, что div добавляется к элементу родительского выбора, который в случае d3.selectAll() является самим документом. , а не SVG (и не тело), несмотря на мой селектор:
var svg = d3.select("body").append("svg");
svg.append("circle")
.attr("cx",40)
.attr("cy",40)
.attr("r",20)
.attr("fill","orange");
var circles = d3.selectAll("svg circle")
.data(["steelblue","yellow"])
.attr("fill",function(d) { return d; });
circles.enter().append("div")
.html(function(d) { return d; });
<script src = "https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>Хорошо, но почему D3 такой? В конечном счете, я не могу ответить, почему, потому что это результат решения, принятого другими людьми, а не мной. Я бы сказал, что некоторые рассуждения могут быть примерно такими:
Если такие селекторы, как (#bargraph rect), определяют, где должны быть введены элементы, тогда могут возникнуть определенные проблемы в зависимости от селектора:
bargraph - возможно, вы хотите ввести элементы в другом месте (но все же необходимо выбрать только определенные дочерние элементы элемента с идентификатором bargraph).Разумеется, последние два относятся к классу, а не к идентификатору, но поведение должно быть одинаковым независимо от строки селектора (различное поведение для идентификаторов, классов и элементов в строке селектора, вероятно, сбивает с толку). Выбранный подход, вероятно, был выбран теми, кто принимал решение, как наиболее чистый и понятный для программиста.
Ах, так оно и есть (я уверен, что вы испытали это на себе), хотя в последнее время мне повезло с несколькими вопросами, которые немного интереснее обычных.
Ну, я теряю интерес к ТАК ... Все вопросы кажутся одинаковыми, только самые простые вещи.
Что ж, вы определенно потратили на это очень много времени. Хотя в последнее время кажется медленнее, возможно, так лучше, чтобы я мог больше работать над некоторыми побочными проектами.
Здесь очень мало интересных вопросов / ответов, таких как этот, который после 35 просмотров не получил голосов. Странный.