Ответ 1
Это назначение ключевой функции , второй аргумент selection.data: он позволяет вам поддерживать постоянство объекта, контролируя, какая привязка привязывается к какому элементу. Например, скажем, у вас был массив объектов, представляющих фрукты:
var fruits = [
{name: "orange", value: 200},
{name: "apple", value: 124},
{name: "banana", value: 32}
];
Когда вы сначала создаете элементы, вам не нужна ключевая функция, потому что существуют любые существующие элементы, и поэтому вы можете использовать стандартный шаблон selectAll-data-enter-append:
var div = d3.select("body").selectAll(".fruit")
.data(fruits)
.enter().append("div")
.attr("class", "fruit")
.text(function(d) { return d.name + ": " + d.value; });
Результат этой операции:
<body>
<div class="fruit">orange: 200</div>
<div class="fruit">apple: 124</div>
<div class="fruit">banana: 32</div>
</body>
Но теперь можно сказать, что ваши данные изменяются, и вы хотите обновить их, чтобы отразить новые данные. Эти новые данные могут быть в другом порядке, и некоторые элементы могут быть добавлены или удалены:
var fruits2 = [
{name: "apple", value: 124},
{name: "lemon", value: 17},
{name: "banana", value: 32},
{name: "strawberry", value: 1465}
];
Яблоко и банан были в исходных данных, и поэтому мы хотим их сохранить. Это называется выбором обновления. Клубника и лимон - новые; это выбор ввода. И, наконец, оранжевый ушел, образуя выбор выхода.
Используя ключевую функцию, которая ссылается на свойство name
базы данных, мы можем назначить новые данные старым элементам по назначению. Затем мы можем создать входящий плод и удалить выходящий плод:
var div = d3.select("body").selectAll(".fruit")
.data(fruits2, function(d) { return d.name; });
div.enter().append("div")
.attr("class", "fruit")
.text(function(d) { return d.name + ": " + d.value; });
div.exit().remove();
Это называется общим шаблоном обновления . (Вы могли бы сделать это в первый раз, это более общая форма шаблона selectAll-data-enter-append.) Результат:
<body>
<div class="fruit">apple: 124</div>
<div class="fruit">banana: 32</div>
<div class="fruit">lemon: 17</div>
<div class="fruit">strawberry: 1465</div>
</body>
Пока порядок выбора div
соответствует данным fruit2
, порядок в DOM не потому, что элементы ввода были добавлены в конец тела. (selection.append не имеет никакой логической логики, чтобы гарантировать заказ, он просто добавляет новые элементы в конец родителя.) При использовании SVG мы часто не заботимся о порядке элементов DOM, потому что все позиционируется абсолютно. Если вы позаботились о заказе, вы можете использовать selection.order, чтобы исправить его после ввода:
div.order(); // make the DOM element order match the selection
Кроме того, в этом примере нам не нужно вносить какие-либо изменения в выбор обновления, потому что значения для apple и banana не изменились. Если данные обновления также изменяются, вы можете совершать вызовы цепочки на selection.attr и selection.text непосредственно из вызова select.data выше.