appendChild() удаляет содержимое из импортированного шаблона

Я получаю активную копию HTML5 <template> с помощью функции importNode():

  function getTemplate() {
    var t = document.getElementById("example");
    return document.importNode(t.content,true);
  }

После этого я заполняю динамические данные,

  var t = fillTemplate({
    id:"test",
    text:"Enter test data"
  });

и, наконец, я добавляю узел в целевой контейнер:

  var c = document.getElementById("container");
  var result = c.appendChild(t);

Моя проблема: узел result лишен всего своего содержимого: я не могу получить доступ к составным элементам шаблона в узле результата. На самом деле узел result не содержит дочерних узлов после выполнения операции appendChild.

Я ожидаю, что возвращаемое значение appendChild должно указывать на узел, который был вставлен в контейнер и теперь является частью активного документа. Любое объяснение, почему это не так?

Вот jsfiddle (проверено в Chrome 53):

https://jsfiddle.net/rplantiko/mv2rbhym/


person rplantiko    schedule 02.10.2016    source источник
comment
Если доступен jquery, используйте clone()   -  person ch271828n    schedule 02.10.2016
comment
@TurtIe Я работаю со знаменитым фреймворком Vanilla JS (загрузка 0 байт) :-) Я могу получить то, что мне нужно, проверив контейнер после операции appendChild. Я просто хочу знать, почему я не могу также проверить возвращаемое значение appendChild.   -  person rplantiko    schedule 02.10.2016


Ответы (1)


Это связано с тем, что вы манипулируете не Node, а DocumentFragment.

Если вы хотите получить количество вставленных узлов, вы должны выполнить вызов родительского контейнера (c в вашем примере), после чего вы получите правильный ответ (5).

Но если вы хотите посчитать только добавленные вами дочерние элементы, вам следует использовать не childNodes, а свойство интерфейса ParentNode children:

c.childNodes.length  // = 5
c.children.length    // = 2

После присоединения к контейнеру c DocumentFragment t больше не имеет дочерних элементов.

Из документации MDN:

Различные другие методы могут принимать фрагмент документа в качестве аргумента (например, любые методы интерфейса Node, такие как Node.appendChild и Node.insertBefore), и в этом случае дочерние элементы фрагмента добавляются или вставляются в то место в DOM, куда вы вставляете фрагмент документа, а не сам фрагмент. Сам фрагмент продолжает существовать (в памяти), но теперь не имеет дочерних элементов.

рекомендация DOM 3 W3C также ясно:

Более того, различные операции, такие как вставка узлов в качестве потомков другого узла, могут принимать объекты DocumentFragment в качестве аргументов; это приводит к тому, что все дочерние узлы DocumentFragment перемещаются в список дочерних элементов этого узла.

person Supersharp    schedule 02.10.2016
comment
Да, t — это фрагмент документа. Но перед выполнением оператора c.appendChild(t) он имеет потомков — после этого он пуст, как result операции. Почему оно меняется? Это должна быть ссылка на один и тот же фрагмент, с тем же содержимым, что и раньше, а не пустой узел фрагмента документа. - person rplantiko; 03.10.2016
comment
Изменяется то, что DocumentFragment не действует как узел, потому что он не является узлом, поэтому вы не можете ожидать поведения чего-то, чем он не является. Я добавил цитату из документа и спецификации. - person Supersharp; 03.10.2016