使用内置的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
的直接子。 这会导致这些元素消失,如果您尝试设置div
的innerHTML
来包含它们。 由于<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的链式函数调用方式。