使用document.createDocumentFragment()和innerHTML来操作DOM

时间:2011-11-20 14:32:26

标签: javascript dom dom-manipulation

我正在创建一个文档片段如下:

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。

9 个答案:

答案 0 :(得分:24)

can't set the innerHTML of a document fragment就像使用普通节点一样,这就是问题所在。添加标准div并设置innerHTML是常见的解决方案。

答案 1 :(得分:12)

虽然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>元素作为子元素。

注意: DocumentFragment仍然会删除<head><body>代码,因此它也不会做你想做的事情。你真的需要创建一个全新的Document

答案 2 :(得分:5)

我知道这个问题已经过时了,但我在玩文档片段时遇到了同样的问题,因为我没有意识到我必须在它上面附加一个div并使用div的innerHTML来加载字符串HTML中的并从中获取DOM元素。关于如何做这类事情我还有其他答案,更适合整个文档。

在firefox(23.0.1)中,设置文档片段的innerHTML属性似乎不会自动生成元素。只有在将片段附加到文档后才能创建元素。

要创建整个文档,请使用document.implementation方法(如果它们受支持)。我在Firefox上取得了成功,但我还没有真正在其他浏览器上测试过。您可以在AtropaToolbox中查看HTMLParser.js以获取使用document.implementation方法的示例。我已经将这段脚本用于XMLHttpRequest页面并操纵它们或从中提取数据。页面中的脚本不会执行,这是我想要的,虽然它可能不是你想要的。我使用这个相当冗长的方法而不是尝试直接使用XMLHttpRequest对象提供的解析的原因是我在解析错误时遇到了相当多的麻烦,我想指定doc应该被解析为HTML 4 Transitional,因为它似乎采取了各种各样的slop并产生了一个DOM。

还有一个DOMParser可供您使用。 Eli Gray在MDN页面上为没有DOMParser但支持document.implementation.createHTMLDocument的浏览器实施了一项实现。 DOMParser的规范指定不执行页面中的脚本并呈现noscript标记的内容。

如果你真的需要在页面中启用脚本,你可以创建一个高度为0,宽度为0,没有边框等的iFrame。它仍然会在页面中,但你可以很好地隐藏它。

还可以选择使用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的无头可编写脚本的Web浏览器。您可以访问本地文件系统,并且可以随心所欲地执行任何操作。我真的不知道你要用整页脚本和操作来完成什么。

答案 3 :(得分:2)

对于Firefox附加组件,使用document.implementation.createHTMLDocument方法可能更有意义,然后从提供给您的DOM开始。

答案 4 :(得分:1)

使用文档片段,您将附加使用document.createElement('yourElement')创建的元素。 aWholeHTMLDocument仅仅是文字。此外,除非您使用框架,否则我不确定为什么您需要创建整个HTML文档,只需使用<body>标记内的内容。

答案 5 :(得分:1)

DocumentFragment继承自Node,但不继承自包含.innerHTML属性的Element

在您的情况下,我将使用<template>标签。 In从Element继承而来,它具有一个漂亮的HTMLTemplateElement.content属性,可为您提供DocumentFragment

这是您可以使用的简单帮助方法:

export default function StringToFragment(string) {
    var renderer = document.createElement('template');
    renderer.innerHTML = string;
    return renderer.content;
}

答案 6 :(得分:0)

使用 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);

答案 7 :(得分:0)

这是一个将 HTML 字符串转换为 DOM 对象的解决方案:

let markup = '<!doctype html><html><head></head><body><h1>hello world</h1></body></html>';
let range = document.createRange();
let fragment = range.createContextualFragment(markup); //Creates a DOM object

该字符串不需要是完整的 HTML 文档。

答案 8 :(得分:-1)

使用querySelector()获取文档片段的子元素(您可能需要正文或正文的某个子元素)。然后获取innerHTML。

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

aWholeHTMLDocument.querySelector("body").childNodes;

请参阅https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment.querySelector

相关问题