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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8202195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:05:09  来源:igfitidea点击:

using document.createDocumentFragment() and innerHTML to manipulate a DOM

javascriptdomdom-manipulation

提问by Loic Duros

I'm creating a document fragment as follow:

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

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

The variable aWholeHTMLDocumentcontains a long string that is the entire html document of a page, and I want to insert it inside my fragmentin order to generate and manipulate the DOM dynamically.

该变量aWholeHTMLDocument包含一个长字符串,它是页面的整个 html 文档,我想将它插入到我的片段中,以便动态生成和操作 DOM。

My question is, once I have added that string to frag.innerHTML, shouldn't it load this string and convert it to a DOM object?

我的问题是,一旦我将该字符串添加到frag.innerHTML,它不应该加载该字符串并将其转换为 DOM 对象吗?

After setting innerHTML, shouldn't I have access to the DOM through a property?

设置innerHTML后,我不应该通过属性访问DOM吗?

I tried frag.childNodes but it doesn't seem to contain anything, and all I want is to just access that newly created DOM.

我试过 frag.childNodes 但它似乎不包含任何东西,我想要的只是访问新创建的 DOM。

采纳答案by Johan

You can't set the innerHTML of a document fragmentlike you would do with a normal node, that's the problem. Adding a standard div and setting the innerHTML of that is the common solution.

不能像处理普通节点那样设置文档片段的 innerHTML,这就是问题所在。添加一个标准的 div 并设置其 innerHTML 是常见的解决方案。

回答by chowey

While DocumentFragmentdoes not support innerHTML, <template>does.

虽然DocumentFragment不支持innerHTML<template>

The contentproperty of a <template>element is a DocumentFragmentso it behaves the same way. For example, you can do:

元素的content属性<template>是 aDocumentFragment因此它的行为方式相同。例如,您可以执行以下操作:

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

The above example is important because you could not do this with innerHTMLand e.g. a <div>, because a <div>does not allow <tr>elements as children.

上面的例子很重要,因为你不能用innerHTMLand来做到这一点,例如 a <div>,因为 a<div>不允许<tr>元素作为子元素。



NOTE:A DocumentFragmentwill still strip the <head>and <body>tags, so it won't do what you want either. You really need to create a whole new Document.

注意:ADocumentFragment仍会去除<head><body>标签,因此它也不会执行您想要的操作。您确实需要创建一个全新的Document.

回答by pekaaw

DocumentFragmentinherits from Node, but not from Elementthat contains the .innerHTMLproperty.

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

In your case I would use the <template>tag. In inherits from Elementand it has a nifty HTMLTemplateElement.contentproperty that gives you a DocumentFragment.

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

Here's a simple helpermethod you could use:

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

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

回答by Kastor

I know this question is old, but I ran into the same issue while playing with a document fragment because I didn't realize that I had to append a div to it and use the div's innerHTMLto load strings of HTML in and get DOM Elements from it. I've got other answers on how to do this sort of thing, better suited for wholedocuments.

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

In firefox (23.0.1) it appears that setting the innerHTML property of the document fragment doesn't automatically generate the elements. It is only after appending the fragment to the document that the elements are created.

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

To create a wholedocument use the document.implementationmethods if they're supported. I've had success doing this on Firefox, I haven't really tested it out on other browsers though. You can look at HTMLParser.jsin the AtropaToolbox for an example of using document.implementationmethods. I've used this bit of script to XMLHttpRequestpages and manipulate them or extract data from them. Scripts in the page are not executed though, which is what I wanted though it may not be what you want. The reason I went with this rather verbose method instead of trying to use the parsing available from the XMLHttpRequestobject directly was that I ran into quite a bit of trouble with parsing errors at the time and I wanted to specify that the doc should be parsed as HTML 4 Transitional because it seems to take all kinds of slop and produce a DOM.

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

There is also a DOMParseravailable which may be easier for you to use. There is an implementation by Eli Grey on the page at MDN for browsers that don't have the DOMParserbut do support document.implementation.createHTMLDocument. The specs for DOMParserspecify that scripts in the page are not executed and the contents of noscript tags be rendered.

还有一个DOMParser可用的,可能更容易让您使用。Eli Gray 在 MDN 的页面上为没有DOMParser但支持document.implementation.createHTMLDocument. DOMParser指定不执行页面中的脚本并呈现 noscript 标签的内容的规范。

If you really need scripts enabled in the page you could create an iFrame with 0 height, 0 width, no borders, etc. It would still be in the page but you could hide it pretty well.

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

There's also the option of using window.open()with document.write, DOM methods or whatever you like. Some browsers even let you do data URI's now.

还可以选择使用window.open()with 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);

So, you do have a few options for creating wholedocuments offscreen/hidden and manipulating them, all of which support loading the document from strings.

因此,您确实有一些选项可用于创建屏幕外/隐藏的整个文档并对其进行操作,所有这些都支持从字符串加载文档。

There's also phantomjs, an awesome project producing a headless scriptable web browser based on webkit. You'll have access to the local filesystem and be able to do pretty much whatever you want. I don't really know what you're trying to accomplish with your full page scripting and manipulation.

还有phantomjs,这是一个很棒的项目,它生成基于 webkit 的无头脚本化 Web 浏览器。您将可以访问本地文件系统,并且几乎可以做任何您想做的事情。我真的不知道你想用你的整页脚本和操作来完成什么。

回答by Gijs

For a Firefox add-on, it probably makes more sense to use the document.implementation.createHTMLDocumentmethod, and then go from the DOM that gives you.

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

回答by Tony Jin

Use appendChild

使用appendChild

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

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

var fragment = document.createDocumentFragment();
... fragment.appendChild(some element);
document.querySelector('blah').appendChild(fragment);

回答by qw3n

With a document fragment you would append elements that you had created with document.createElement('yourElement'). aWholeHTMLDocumentis merely text. Also, unless your using frames I'm not sure why you would need to create the whole HTML document just use what is inside the <body>tags.

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

回答by Phyxx

Use querySelector() to get a child of the document fragment (you probably want the body, or some child of the body). Then get the innerHTML.

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

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

or

或者

aWholeHTMLDocument.querySelector("body").childNodes;

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

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