使用内置的DOM方法或原型从HTMLstring中创build一个新的DOM元素

我正在尝试使用HTMLstringdynamic创build一个元素。 这是一个使用原型和DOM的简单示例:

// HTML string var s = '<li>text</li>'; // DOM var el1 = document.createElement(s); // prototype var el2 = new Element(s); $('mylist').appendChild(el1); $('mylist').appendChild(el2); 

两种方法都将一个空的listitem插入到列表中。

我知道使用原型的元素作为构造函数需要一个tagName和一个可选的属性参数,但我想它可能让我传入一个HTMLstring。

但是, MSDN指出:“你也可以通过使用方法参数的HTMLstring来指定createElement方法中的所有属性”…所以我不确定是什么问题。

是的,我知道我可以在jQuery中轻松地做到这一点,不幸的是,我们没有使用jQuery。 我在这里俯瞰真正简单的东西吗?

应该是显而易见的,但是到那个MSDN文章的链接是关于一个仅IE的function。

一般来说,下面的跨浏览器技巧是所有库从HTMLstring获取DOM元素的做法(对于<td> s, <tr> s, <thead> s, <select> s和更多):

 var s = '<li>text</li>'; // HTML string var div = document.createElement('div'); div.innerHTML = s; var elements = div.childNodes; 

或者var element = div.firstChild如果你知道你正在得到一个根节点。

我build议你坚持从HTMLstring创build元素的图书馆批准的方法。 Prototype内置了update()方法 。

HTML 5引入了可用于此目的的<template>元素( spec , MDN docs )。

一个<template>是一个HTML元素,允许任何其他的元素types作为子元素。 该template具有一个.content属性,您可以使用指向带有模板内容的DocumentFragment JavaScript进行访问。 这意味着您可以通过设置<template>元素的innerHTML ,然后到达template.content属性,将HTMLstring转换为DOM元素。

例子:

 /** * @param {String} HTML representing a single element * @return {Element} */ function htmlToElement(html) { var template = document.createElement('template'); template.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>'); 

请注意, 使用不同容器元素(如div类似方法并不完美。 HTML对哪些元素types被允许存在于其他元素types中有限制; 例如,你不能把一个td作为一个div的直接子。 这会导致这些元素消失,如果您尝试设置divinnerHTML来包含它们。 由于<template>对其内容没有这样的限制,所以在使用模板时这个缺点不适用。

但是, template是相当新的,支持还是有点片面的。 截至2016年2月,我可以使用的估计有71%的用户正在使用支持template的浏览器 。 特别是没有Internet Explorer版本支持它们; 在发布Edge之前,微软并没有实现template支持。

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

新的DOM实现有range.createContextualFragment ,它以独立于框架的方式完成你想要的function。

它被广泛支持。 可以肯定的是,在相同的MDN链接中检查其兼容性 ,因为它将会改变。 截至2017年5月,这是它:

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

下面是一个简单的方法来做到这一点:

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

通过Prototype,你也可以这样做:

HTML:

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

JS:

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

不需要任何调整,你有一个本地API:

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

对于像<td>test</td>这样的特定html片段,div.innerHTML,DOMParser.parseFromString和range.createContextualFragment(没有正确的上下文)将不会创build<td>元素。

jQuery.parseHTML()处理它们(我将jQuery 2的parseHTML函数提取为一个独立的要点 )。

对于Edge 13+,使用模板标签:

 function parseHTML(html) { var t = document.createElement('template'); t.innerHTML = html; return t.content.cloneNode(true); } var documentFragment = parseHTML('<td>Test</td>'); 

这是我的代码,它的工作原理:

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

您可以使用以下命令从string创build有效的DOM节点:

document.createRange().createContextualFragment()

以下示例在页面中添加一个button元素,并从string中获取标记:

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

晚了,但只是一个说明;

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

/ /testing铬23.0,火狐18.0,即7-8-9和歌剧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 element targetElement.appendChild(foo) // Add event foo.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 element targetElement.removeChild(foo) } </script> 

我正在使用这个方法(工作在IE9 +),虽然它不会parsing<td>或其他一些无效的身体直接孩子:

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

使用insertAdjacentHTML()。 它适用于所有目前的浏览器,即使IE11。

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

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

 /*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')" })); 

你可以试试这个dom-builder从你的js代码构造html元素

您可以使用以下function将文本“HTML”转换为元素

 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中创build一个元素的原型:

 Document.prototype.createElementFromString = function (str) { const element = new DOMParser().parseFromString(str, 'text/html'); const child = element.documentElement.querySelector('body').firstChild; return child; }; 
 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); 
 var jtag = $j.li({ child:'text' }); // Represents: <li>text</li> var htmlContent = $('mylist').html(); $('mylist').html(htmlContent + jtag.html()); 

使用jnerator

如果你的JavaScript依赖于jQuery,那么使用append 。 例:

 $('[data-label="tid_0"]').append('<datalist id="strikes"><option>a</option><option>10d</option><option>30d</option><option>30f</option></datalist>'); 

对应的jQuery API

这也将工作:

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

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