2017-01-21 11 views
3

Полагаю, что цель DocumentFragment состоит в том, чтобы иметь возможность конструировать содержимое, не касаясь DOM, пока оно не будет готово к работе.JavaScript: Копировать узел в DocumentFragment

Учитывая, что DocumentFragment не поддерживает innerHTML, это может быть немного утомительно. С другой стороны, после его создания легко добавить содержимое к существующему узлу DOM самим фрагментом.

Если я создаю div, не добавляя его в DOM, я могу заполнить его, как мне нравится, в том числе innerHTML. Насколько я могу судить, он не должен оказывать дополнительного влияния на производительность.

Есть ли простой способ (то есть в одной строке или около того) скопировать содержимое существующего узла DOM в DocumentFragment? Процесс будет выглядеть так:

var div=document.createElement('div'); 
var fragment=document.createDocumentFragment(); 
div.innerHTML='…'; 
// copy contents to fragment 
// etc 

Таким образом, я мог бы иметь лучшее из обоих миров.

Ответ

Вот ответ на @KevBot ниже включены в пример:

var divTest=document.querySelector('div#test'); 

var html='<p>One</p><p>Two</p>'; 
var fragment=document.createRange().createContextualFragment(html); 

divTest.appendChild(fragment); 
+0

Мне нравится этот вопрос, некоторые из этих решений реализуют некоторые неясные JavaScript. – zer00ne

+0

* Если я создаю div без добавления его в DOM, я могу заполнить его, как мне нравится, включая innerHTML. Насколько я могу судить, это не должно оказывать никакого дополнительного влияния на производительность. * Разница между div и docFrag заключается в том, что когда вы добавляете div в DOM, он остается там со всем, что вы добавили к нему. С docFrag вы добавляете его в DOM, и все, что вы добавили к нему, находится в DOM, но docFrag - нет. Как будто это тряпка скатертей, когда вы выдергиваете скатерть, но оставляйте тарелки на столе. – zer00ne

ответ

3

Да, вы можете легко создать фрагмент с последовательностью HTML с использованием метода document.createRange.

document.createRange возвращает объект Range, у которого есть метод под названием createContextualFragment, который позволяет получить фрагмент только из HTML.

function fragmentFromString(strHTML) { 
 
    return document.createRange().createContextualFragment(strHTML); 
 
} 
 

 
let div = document.createElement('div'); 
 
div.innerHTML = '<p>Testing</p>'; 
 

 
let fragment = fragmentFromString(div.innerHTML); 
 
console.log(fragment);
<div> 
 
    <p>Random Content</p> 
 
</div>

работает во всех основных браузерах и IE11.

+0

Спасибо за ответ. Тот факт, что он работает в IE11, немного сокращает его, но кто все равно заботится обо всем остальном? Я изменил свой вопрос, чтобы отразить ваш пример. – Manngo

+0

Добро пожаловать. Да, даже Microsoft в этот момент отказалась от поддержки на 10 и ниже. – KevBot

1

Вы можете использовать appendChild, чтобы добавить новый элемент к фрагменту.

var div=document.createElement('div'); 
var fragment=document.createDocumentFragment(); 
div.innerHTML='…'; 

fragment.appendChild(div); 

Если вы хотите, чтобы ввести содержимое элемента в фрагмент, то вы можете перебрать childNodes и вставить их в фрагмент.

div.childNodes.forEach(function(node) { 
    fragment.appendChild(node); 
}); 
+0

Спасибо за ответ, но я не хочу сам 'div'. Просто содержимое. – Manngo

+0

Вы можете использовать свойство 'childNodes' и перебирать по каждому узлу и вводить его в фрагмент. 'div.childNodes.forEach (function (node) { fragment.appendChild (node); });' –

1

Попробуйте это за размер

text = frag.appendChild(document.createTextNode("insert text here")) 

или

text = frag.appendChild(document.createTextNode(div.innerHTML)) 

или

text = frag.appendChild(document.createTextNode(div.textContent)) 

Переменная text проведет TextNode в то время как вы также приложили к TextNode все в одной строке

3

Вы можете создать элемент <template>, являющийся фрагментом документа; набор .innerHTML из template элемента, и получить .innerHTML из template элемента с помощью .content свойства

var template = document.createElement("template"); 
 
var div = document.createElement("div"); 
 
div.innerHTML = "<p>abc</p>"; 
 
template.innerHTML = div.innerHTML; 
 
document.body.appendChild(template.content);