использование document.createDocumentFragment () и innerHTML для манипулирования DOM - PullRequest
29 голосов
/ 20 ноября 2011

Я создаю фрагмент документа следующим образом:

var aWholeHTMLDocument = '<!doctype html> <html><head></head><body><h1>hello world</h1></body></html>';
var frag = document.createDocumentFragment();
frag.innerHTML = aWholeHTMLDocument;

Переменная aWholeHTMLDocument содержит длинную строку, представляющую собой весь HTML-документ страницы, и я хочу вставить ее в свой фрагмент по порядкудля динамического создания и манипулирования dom.

Мой вопрос: как только я добавлю эту строку в frag.innerHTML, не должен ли он загрузить эту строку и преобразовать ее в объект DOM?После установки innerHTML, я не должен иметь доступ к DOM через свойство?Я попробовал frag.childNodes, но, похоже, он ничего не содержит, и все, что я хочу, - это просто получить доступ к этому недавно созданному DOM.

Ответы [ 8 ]

25 голосов
/ 20 ноября 2011

Вы не можете установить innerHTML фрагмента документа , как вы это сделали бы с обычным узлом, вот в чем проблема. Добавление стандартного div и установка innerHTML этого является общим решением.

16 голосов
/ 21 ноября 2017

Хотя DocumentFragment не поддерживает innerHTML, <template> поддерживает .

Свойство content элемента <template> является DocumentFragment, поэтому оно ведет себя так же. Например, вы можете сделать:

var tpl = document.createElement('template');
tpl.innerHTML = '<tr><td>Hello</td><td>world</td></tr>';
document.querySelector('table').appendChild(tpl.content);

Приведенный выше пример важен, потому что вы не можете сделать это с помощью innerHTML и, например, <div>, поскольку <div> не допускает элементы <tr> в качестве дочерних.


ПРИМЕЧАНИЕ: A DocumentFragment будет по-прежнему удалять теги <head> и <body>, поэтому он также не будет выполнять то, что вы хотите. Вам действительно нужно создать совершенно новый Document.

5 голосов
/ 04 сентября 2013

Я знаю, что этот вопрос старый, но я столкнулся с той же проблемой, играя с фрагментом документа, потому что я не понимал, что мне нужно добавить к нему div и использовать innerHTML div для загрузки строк HTMLи получить элементы DOM от него.У меня есть другие ответы о том, как это сделать, лучше подходит для целых документов.

В Firefox (23.0.1) кажется, что установка свойства innerHTML документафрагмент не генерирует автоматически элементы.Только после добавления фрагмента в документ создаются элементы.

Для создания целого документа используйте методы document.implementation, если они поддерживаются,Я добился успеха в этом в Firefox, хотя я не проверял его в других браузерах.Вы можете посмотреть HTMLParser.js в AtropaToolbox для примера использования document.implementation методов.Я использовал этот фрагмент скрипта для XMLHttpRequest страниц и манипулирования ими или извлечения данных из них.Скрипты на странице не выполняются, хотя это то, что я хотел, хотя это может быть не то, что вы хотите.Причина, по которой я выбрал этот довольно многословный метод, вместо того, чтобы пытаться использовать синтаксический анализ, доступный непосредственно из объекта XMLHttpRequest, заключалась в том, что в то время я столкнулся с множеством проблем с ошибками синтаксического анализа и хотел указать, что документ должен бытьанализируется как HTML 4 Transitional, потому что кажется, что он принимает все помои и создает DOM.

Также доступно DOMParser, которое может быть проще в использовании.На странице MDN есть реализация Eli Grey для браузеров, которые не имеют DOMParser, но поддерживают document.implementation.createHTMLDocument.Спецификации для DOMParser указывают, что сценарии на странице не выполняются, а содержимое тегов noscript должно отображаться.

Если вам действительно нужны сценарии на странице, вы можете создать iFrame с 0 высотой, 0 ширинойбез границ и т. д. Он все равно будет на странице, но вы можете его довольно хорошо скрыть.

Существует также возможность использования window.open() с document.write, методами DOM или любым другим способом.Некоторые браузеры теперь даже позволяют вам делать URI данных.

var x = window.open( 'data:text/html;base64,' + btoa('<h1>hi</h1>') );
// wait for the document to load. It only takes a few milliseconds
// but we'll wait for 5 seconds so you can watch the child window
// change.
setTimeout(function () {
    console.log(x.document.documentElement.outerHTML);
    x.console.log('this is the console in the child window');
    x.document.body.innerHTML = 'oh wow';
}, 5000);

Итак, у вас есть несколько вариантов создания целых документов вне экрана / скрытых и манипулирования ими, все из которых поддерживают загрузкудокумент из строк.

Существует также phantomjs , потрясающий проект, создающий веб-браузер без скриптов на основе скриптов на основе webkit.Вы получите доступ к локальной файловой системе и сможете делать практически все, что захотите.Я действительно не знаю, чего вы пытаетесь достичь с помощью сценариев и манипуляций на всей странице.

2 голосов
/ 08 марта 2012

Для дополнения Firefox, вероятно, имеет смысл использовать метод document.implementation.createHTMLDocument, а затем перейти от DOM, который дает вам.

1 голос
/ 21 февраля 2019

DocumentFragment наследуется от Node, но не от Element, который содержит свойство .innerHTML.

В вашем случае я бы использовал тег <template>.In наследует от Element и обладает отличным свойством HTMLTemplateElement.content, которое дает вам DocumentFragment.

Вот простой вспомогательный метод, который вы можете использовать:

export default function StringToFragment(string) {
    var renderer = document.createElement('template');
    renderer.innerHTML = string;
    return renderer.content;
}
1 голос
/ 20 ноября 2011

С фрагментом документа вы добавляете элементы, которые вы создали с помощью document.createElement('yourElement'). aWholeHTMLDocument это просто текст. Кроме того, если вы не используете фреймы, я не уверен, зачем вам нужно создавать весь HTML-документ, просто используйте то, что находится внутри <body> тегов.

0 голосов
/ 04 мая 2016

Использование appendChild

см. https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

var fragment = document.createDocumentFragment();
... fragment.appendChild(some element);
document.querySelector('blah').appendChild(fragment);
0 голосов
/ 06 января 2014

Используйте querySelector (), чтобы получить дочерний элемент фрагмента документа (вам, вероятно, нужно тело или некоторый дочерний элемент тела). Тогда получите innerHTML.

document.body.innerHTML = aWholeHTMLDocument.querySelector("body").innerHTML

или

aWholeHTMLDocument.querySelector("body").childNodes;

См. https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment.querySelector

...