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

问题描述 投票:28回答:8

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

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。

javascript dom dom-manipulation
8个回答
25
投票

你和can't set the innerHTML of a document fragment一样,你会做一个正常的节点,这就是问题所在。添加标准div并设置innerHTML是常见的解决方案。


18
投票

虽然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


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


2
投票

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


2
投票

DocumentFragment继承自Node,但不是来自包含Element财产的.innerHTML

在你的情况下,我会使用<template>标签。继承自Element,它有一个漂亮的HTMLTemplateElement.content属性,给你一个DocumentFragment

这是一个你可以使用的简单助手方法:

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

1
投票

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


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

-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

© www.soinside.com 2019 - 2024. All rights reserved.