使用内置DOM方法或原型从超文本标记语言字符串创建新的DOM元素

我有一个表示元素的超文本标记语言字符串:'<li>text</li>'。我想将它附加到DOM中的元素(在我的情况下是ul)。我如何使用原型或DOM方法执行此操作?

(我知道我可以在jQuery中轻松做到这一点,但不幸的是我们没有使用jQuery。

844196 次浏览

备注:大多数当前浏览器支持超文本标记语言<template>元素,它提供了一种更可靠的从字符串转向创建元素的方法。参见马克·阿梅里的答案如下

对于较旧的浏览器和node/jsdom:(在撰写本文时还不支持<template>元素),使用以下方法。从超文本标记语言字符串中获取DOM元素与库使用的方法相同(为IE做一些额外的工作通过其innerHTML的实现解决错误):

function createElementFromHTML(htmlString) {var div = document.createElement('div');div.innerHTML = htmlString.trim();
// Change this to div.childNodes to support multiple top-level nodes.return div.firstChild;}

请注意,与超文本标记语言模板不同,此不会适用于某些不能合法成为<div>子元素的元素,例如<td>

如果您已经在使用库,我建议您坚持使用库批准的从超文本标记语言字符串创建元素的方法:

以下是如何使用代码类型(正如OP 12年前最初要求的那样):

超文本标记语言:

<ul id="mylist"></ul>

js:

$('mylist').insert('<li>text</li>');

注意这不是jQuery!

这是我的代码,它是有效的:

function parseTableHtml(s) { // s is stringvar div = document.createElement('table');div.innerHTML = s;
var tr = div.getElementsByTagName('tr');// ...}

较新的DOM实现有range.createContextualFragment,它以独立于框架的方式执行您想要的操作。

它得到了广泛的支持。不过,可以肯定的是,在同一个MDN链接中,检查其兼容性下降了,因为它会发生变化。截至2017年5月,这是它:

Feature         Chrome   Edge   Firefox(Gecko)  Internet Explorer   Opera   SafariBasic support   (Yes)    (Yes)  (Yes)           11                  15.0    9.1.2

这也将工作:

$('<li>').text('hello').appendTo('#mylist');

它感觉更像是一种带有链式函数调用的jQuery方式。

var jtag = $j.li({ child:'text' }); // Represents: <li>text</li>var htmlContent = $('mylist').html();$('mylist').html(htmlContent + jtag.html());

使用jnerator

迟到,但只是一个音符;

可以将一个平凡的元素添加到目标元素作为容器,并在使用后将其删除。

//在chrome 23.0,Firefox 18.0,即7-8-9和Opera 12.11上测试。

<div id="div"></div>
<script>window.onload = function() {var foo, targetElement = document.getElementById('div')foo = document.createElement('foo')foo.innerHTML = '<a href="#" target="_self">Text of A 1.</a> '+'<a href="#" onclick="return !!alert(this.innerHTML)">Text of <b>A 2</b>.</a> '+'<hr size="1" />'// Append 'foo' element to target elementtargetElement.appendChild(foo)
// Add eventfoo.firstChild.onclick = function() { return !!alert(this.target) }
while (foo.firstChild) {// Also removes child nodes from 'foo'targetElement.insertBefore(foo.firstChild, foo)}// Remove 'foo' element from target elementtargetElement.removeChild(foo)}</script>

这里有一个简单的方法来做到这一点:

String.prototype.toDOM=function(){var d=document,i,a=d.createElement("div"),b=d.createDocumentFragment();a.innerHTML=this;while(i=a.firstChild)b.appendChild(i);return b;};
var foo="<img src='//placekitten.com/100/100'>foo<i>bar</i>".toDOM();document.body.appendChild(foo);

为此,我想我会分享我想出的复杂但简单的方法……也许有人会发现一些有用的东西。

/*Creates a new element - By Jamin Szczesny*/function _new(args){ele = document.createElement(args.node);delete args.node;for(x in args){if(typeof ele[x]==='string'){ele[x] = args[x];}else{ele.setAttribute(x, args[x]);}}return ele;}
/*You would 'simply' use it like this*/
$('body')[0].appendChild(_new({node:'div',id:'my-div',style:'position:absolute; left:100px; top:100px;'+'width:100px; height:100px; border:2px solid red;'+'cursor:pointer; background-color:HoneyDew',innerHTML:'My newly created div element!',value:'for example only',onclick:"alert('yay')"}));

对于某些html片段,如<td>test</td>,div.inner超文本标记语言,DOMParser.parseFromString和range.createContextualFrament(没有正确的上下文)解决方案,不会创建<td>元素。

jQuery.parse超文本标记语言()可以正确处理它们(我提取了jQuery 2的parseHTML函数转换为独立函数,可以在非jQuery代码库中使用)。

如果您只支持Edge 13+,则只需使用HTML5模板标签更简单:

function parseHTML(html) {var t = document.createElement('template');t.innerHTML = html;return t.content;}
var documentFragment = parseHTML('<td>Test</td>');
function domify (str) {var el = document.createElement('div');el.innerHTML = str;
var frag = document.createDocumentFragment();return frag.appendChild(el.removeChild(el.firstChild));}
var str = "<div class='foo'>foo</div>";domify(str);

超文本标记语言5引入了可用于此目的的<template>元素(如现在在WhatWG规范MDN文档中所述)。

<template>元素用于声明可在脚本中使用的超文本标记语言片段。该元素在DOM中表示为HTMLTemplateElement,其.content属性为HTMLTemplateElement0类型,以提供对模板内容的访问。这意味着您可以通过设置<template>元素的HTMLTemplateElement1将超文本标记语言字符串转换为DOM元素,然后进入template.content属性。

示例:

/*** @param {String} HTML representing a single element* @return {Element}*/function htmlToElement(html) {var template = document.createElement('template');html = html.trim(); // Never return a text node of whitespace as the resulttemplate.innerHTML = html;return template.content.firstChild;}
var td = htmlToElement('<td>foo</td>'),div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');
/*** @param {String} HTML representing any number of sibling elements* @return {NodeList}*/function htmlToElements(html) {var template = document.createElement('template');template.innerHTML = html;return template.content.childNodes;}
var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');

请注意,类似的方法使用不同的容器元素,例如#0不太有效。超文本标记语言对允许哪些元素类型存在于哪些其他元素类型中有限制;例如,您不能将td作为div的直接子元素。如果您尝试设置divinnerHTML包含这些元素,这会导致这些元素消失。由于<template>对其内容没有这样的限制,因此在使用模板时不适用此缺点。

但是,某些旧浏览器不支持template。截至2021年4月,我可以用…估计全球96%的用户正在使用支持#0的浏览器。特别是,没有Internet Explorer版本支持它们;微软直到Edge发布才实现template支持。

如果你足够幸运,正在编写仅针对现代浏览器用户的代码,请立即使用它们。否则,你可能需要等待一段时间才能赶上用户。

我正在使用这个方法(在IE9+中工作),尽管它不会解析<td>或其他一些无效的body直接子节点:

function stringToEl(string) {var parser = new DOMParser(),content = 'text/html',DOM = parser.parseFromString(string, content);
// return elementreturn DOM.body.childNodes[0];}
stringToEl('<li>text</li>'); //OUTPUT: <li>text</li>

不需要任何调整,你有一个原生API:

const toNodes = html =>new DOMParser().parseFromString(html, 'text/html').body.childNodes[0]

您可以使用以下命令从字符串创建有效的DOM节点:

document.createRange().createContextualFragment()

以下示例在从字符串获取标记的页面中添加一个按钮元素:

let html = '<button type="button">Click Me!</button>';let fragmentFromString = function (strHTML) {return document.createRange().createContextualFragment(strHTML);}let fragment = fragmentFromString(html);document.body.appendChild(fragment);

您可以使用以下函数将文本“超文本标记语言”转换为元素

function htmlToElement(html){var element = document.createElement('div');element.innerHTML = html;return(element);}var html="<li>text and html</li>";var e=htmlToElement(html);

我添加了一个Document原型,它从string创建一个元素:

Document.prototype.createElementFromString = function (str) {const element = new DOMParser().parseFromString(str, 'text/html');const child = element.documentElement.querySelector('body').firstChild;return child;};

用法:

document.createElementFromString("<h1>Hello World!</h1>");

使用//插入参数HTML()。它适用于所有当前浏览器,即使是IE11。

var mylist = document.getElementById('mylist');mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
<ul id="mylist"><li>first</li><li>second</li></ul>

这是我的工作代码

我想将“文本”字符串转换为超文本标记语言元素

var diva = UWA.createElement('div');diva.innerHTML = '<a href="http://wwww.example.com">Text</a>';var aelement = diva.firstChild;

HTML5&ES6

<template>

Demo

"use strict";
/**** @author xgqfrms* @license MIT* @copyright xgqfrms* @description HTML5 Template* @augments* @example**/
/*
<template><h2>Flower</h2><img src="https://www.w3schools.com/tags/img_white_flower.jpg"></template>

<template><div class="myClass">I like: </div></template>
*/
const showContent = () => {// let temp = document.getElementsByTagName("template")[0],let temp = document.querySelector(`[data-tempalte="tempalte-img"]`),clone = temp.content.cloneNode(true);document.body.appendChild(clone);};
const templateGenerator = (datas = [], debug = false) => {let result = ``;// let temp = document.getElementsByTagName("template")[1],let temp = document.querySelector(`[data-tempalte="tempalte-links"]`),item = temp.content.querySelector("div");for (let i = 0; i < datas.length; i++) {let a = document.importNode(item, true);a.textContent += datas[i];document.body.appendChild(a);}return result;};
const arr = ["Audi", "BMW", "Ford", "Honda", "Jaguar", "Nissan"];
if (document.createElement("template").content) {console.log("YES! The browser supports the template element");templateGenerator(arr);setTimeout(() => {showContent();}, 0);} else {console.error("No! The browser does not support the template element");}
@charset "UTf-8";
/* test.css */
:root {--cololr: #000;--default-cololr: #fff;--new-cololr: #0f0;}
[data-class="links"] {color: white;background-color: DodgerBlue;padding: 20px;text-align: center;margin: 10px;}
<!DOCTYPE html><html lang="zh-Hans">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Template Test</title><!--[if lt IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script><![endif]--></head>
<body><section><h1>Template Test</h1></section><template data-tempalte="tempalte-img"><h3>Flower Image</h3><img src="https://www.w3schools.com/tags/img_white_flower.jpg"></template><template data-tempalte="tempalte-links"><h3>links</h3><div data-class="links">I like: </div></template><!-- js --></body>
</html>

var msg="测试"jQuery.parse超文本标记语言

从字符串渲染DOM的最快解决方案:

let render = (relEl, tpl, parse = true) => {if (!relEl) return;const range = document.createRange();range.selectNode(relEl);const child = range.createContextualFragment(tpl);return parse ? relEl.appendChild(child) : {relEl, el};};

并且这里 u可以检查DOM操作React与本机JS的性能

现在你可以简单地使用:

let element = render(document.body, `<div style="font-size:120%;line-height:140%"><p class="bold">New DOM</p></div>`);

当然,在不久的将来,你会使用内存中的引用,因为var“元素”是你在文档中新创建的DOM。

请记住“innerHTML=”非常慢:/

为什么不使用原生js?

    var s="<span class='text-muted' style='font-size:.75em; position:absolute; bottom:3px; left:30px'>From <strong>Dan's Tools</strong></span>"var e=document.createElement('div')var r=document.createRange();r.selectNodeContents(e)var f=r.createContextualFragment(s);e.appendChild(f);e = e.firstElementChild;

答案

  • 创建一个Template
  • Template's innerHTML设置为您的string.trim()
  • 创建ArrayTemplate's个孩子
  • 返回childrenchild

function toElement(s='',c,t=document.createElement('template'),l='length'){t.innerHTML=s.trim();c=[...t.content.childNodes];return c[l]>1?c:c[0]||'';}


console.log(toElement());console.log(toElement(''));console.log(toElement('    '));console.log(toElement('<td>With td</td>'));console.log(toElement('<tr><td>With t</td></tr>'));console.log(toElement('<tr><td>foo</td></tr><tr><td>bar</td></tr>'));console.log(toElement('<div><span>nested</span> <span>stuff</span></div>'));

我从这篇文章链接。将超文本标记语言字符串转换为DOM元素?

对我来说,我想找到一种将字符串转换为超文本标记语言元素的方法。如果你也有这个需求,你可以尝试以下

const frag = document.createRange().createContextualFragment(`<a href="/link.js">js</a><a>go</a>`)const aCollection = frag.querySelectorAll("a")for (let [key, a] of Object.entries(aCollection)) {console.log(a.getAttribute("href"), a.textContent)}

我自己也为此搜索了很多,并找到了这个整洁的解决方案。

const stringToHTML = (str) => {var parser = new DOMParser();var doc = parser.parseFromString(str, 'text/html');return doc.body;};

我想转换的字符串:

'<iframe src="https://player.vimeo.com/video/578680903?h=ea840f9223&amp;app_id=122963" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen title="Total Body Balance"></iframe>'

结果:

<body><iframe src="https://player.vimeo.com/video/578680903?h=ea840f9223&amp;app_id=122963" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen="" title="Total Body Balance"></iframe></body>

最新的JS示例:

<template id="woof-sd-feature-box"><div class="woof-sd-feature-box" data-key="__KEY__" data-title="__TITLE__" data-data="__OPTIONS__"><h4>__TITLE__</h4><div class="woof-sd-form-item-anchor"><img src="img/move.png" alt=""></div></div>
</template>
<script>create(example_object) {let html = document.getElementById('woof-sd-feature-box').innerHTML;html = html.replaceAll('__KEY__', example_object.dataset.key);html = html.replaceAll('__TITLE__', example_object.dataset.title);html = html.replaceAll('__OPTIONS__', example_object.dataset.data);//convertion HTML to DOM element and prepending it into another elementconst dom = (new DOMParser()).parseFromString(html, "text/html");this.container.prepend(dom.querySelector('.woof-sd-feature-box'));}</script>

访问https://www.codegrepper.com/code-examples/javascript/convert+a+string+to+html+element+in+js

const stringToHtml = function (str) {var parser = new DOMParser();var doc = parser.parseFromString(str, 'text/html');return doc.body;}

解决方案-适用于自IE 4.0以来的所有浏览器

var htmlString = `<body><header class="text-1">Hello World</header><div id="table"><!--TABLE HERE--></div></body>`;var tableString = `<table class="table"><thead><tr><th>th cell</th></tr></thead><tbody><tr><td>td cell</td></tr></tbody></table>`;

var doc = document.implementation.createHTMLDocument();doc.open();doc.write(htmlString);doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);doc.close();
console.log(doc);

你可以使用DOMParser

var doc = (new DOMParser).parseFromString(htmlString, "text/html");doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);
console.log(doc);