我有一个表示元素的HTML字符串:'<li>text</li>'
。我想将它附加到DOM中的元素(在我的情况下是ul
)。如何使用Prototype或DOM方法执行此操作?
(我知道我可以在jQuery中轻松完成这个,但不幸的是我们没有使用jQuery。)
注意:大多数当前浏览器都支持HTML <template>
元素,这些元素提供了一种更可靠的方法来转换从字符串创建元素。见Mark Amery's answer below for details。
对于较旧的浏览器和node / jsdom :(在编写时尚不支持<template>
元素),请使用以下方法。图书馆用来从HTML字符串中获取DOM元素是一样的(with some extra work for IE用它的innerHTML
实现来解决bug):
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;
}
请注意,与HTML模板不同,这对于某些不能合法地成为<div>
子元素的元素(例如<td>
s)不起作用。
如果您已经在使用库,我建议您坚持使用库批准的方法从HTML字符串创建元素:
update()
method中内置了此功能。jQuery(html)
和jQuery.parseHTML
方法中实现了它。我正在使用这种方法(在IE9 +中工作),虽然它不会解析<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>
我添加了一个Document
原型,它从字符串创建一个元素:
Document.prototype.createElementFromString = function (str) {
const element = new DOMParser().parseFromString(str, 'text/html');
const child = element.documentElement.querySelector('body').firstChild;
return child;
};
为了进一步增强我们可以在不同地方找到的有用的.toDOM()片段,我们现在可以安全地使用反引号(template literals)。
所以我们可以在foo html声明中使用单引号和双引号。
对于那些熟悉这个术语的人来说,这就像heredocs。
这可以通过变量进一步增强,以进行复杂的模板化:
模板文字由反向标记(
)(严重重音)字符包围,而不是双引号或单引号。模板文字可以包含占位符。这些由美元符号和花括号($ {expression})表示。占位符中的表达式和它们之间的文本将传递给函数。默认函数只是将部分连接成一个字符串。如果模板文字前面有一个表达式(此处为标记),则称为“标记模板”。在这种情况下,标记表达式(通常是函数)将使用已处理的模板文字进行调用,然后您可以在输出之前对其进行操作。要逃避模板文字中的反向标记,请在反向标记之前添加反斜杠\。
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
}
// Using template litterals
var a = 10, b = 5
var foo=`
<img
onclick="alert('The future start today!')"
src='//placekitten.com/100/100'>
foo${a + b}
<i>bar</i>
<hr>`.toDOM();
document.body.appendChild(foo);
img {cursor: crosshair}
那么,为什么不直接使用.innerHTML +=
?通过这样做,浏览器重新计算整个DOM,速度要慢得多。
迟到但只是作为一个笔记;
可以将一个简单的元素添加到目标元素作为容器,并在使用后将其删除。
//在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 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>
这是我的代码,它有效:
function parseTableHtml(s) { // s is string
var div = document.createElement('table');
div.innerHTML = s;
var tr = div.getElementsByTagName('tr');
// ...
}
<template>
演示
"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>
对于它,我想我会分享这个复杂而又简单的方法我想出来......也许有人会找到有用的东西。
/*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')"
}));
var msg =“test”jQuery.parseHTML(msg)
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);
这是我的工作代码
我想将'Text'字符串转换为HTML元素
var diva = UWA.createElement('div');
diva.innerHTML = '<a href="http://wwww.example.com">Text</a>';
var aelement = diva.firstChild;
HTML 5引入了可用于此目的的<template>
元素(现在在WhatWG spec和MDN docs中描述)。
<template>
是一个HTML元素,允许任何其他元素类型作为子元素。 template
有一个.content
属性,你可以用JavaScript访问,它指向带有模板内容的DocumentFragment
。这意味着您可以通过设置innerHTML
元素的<template>
,然后到达template
的.content
属性,将HTML字符串转换为DOM元素。
例子:
/**
* @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 result
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>');
请注意,类似的方法,use a different container element such as a div
不太有效。 HTML限制了允许哪些元素类型存在于哪些元素类型中;例如,你不能把td
作为div
的直接孩子。如果你试图设置innerHTML
的div
来包含它们,这会导致这些元素消失。由于<template>
s对其内容没有此类限制,因此在使用模板时不适用此缺点。
但是,某些旧浏览器不支持template
。截至2018年1月,我可以使用...估计90% of users globally are using a browser that supports template
s。特别是,没有版本的Internet Explorer支持它们;在Edge发布之前,微软没有实施template
支持。
如果您足够幸运能够编写仅针对现代浏览器用户的代码,请立即使用它们。否则,您可能需要等待一段时间才能让用户赶上。
var jtag = $j.li({ child:'text' }); // Represents: <li>text</li>
var htmlContent = $('mylist').html();
$('mylist').html(htmlContent + jtag.html());
使用jnerator
您可以使用以下函数将文本“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);
这也可以:
$('<li>').text('hello').appendTo('#mylist');
感觉更像是链接函数调用的jquery方式。
使用insertAdjacentHTML()。它适用于所有当前的浏览器,即使使用IE11。
var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
<ul id="mylist">
<li>first</li>
<li>second</li>
</ul>
较新的DOM实现具有range.createContextualFragment
,它以与框架无关的方式执行您想要的操作。
它得到了广泛的支持。但是,请确保在相同的MDN链接中检查其兼容性,因为它将会更改。截至2017年5月,这是:
Feature Chrome Edge Firefox(Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) 11 15.0 9.1.2
无需任何调整,您有一个原生API:
const toNodes = html =>
new DOMParser().parseFromString(html, 'text/html').body.childNodes
这是一个简单的方法:
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);
对于某些html片段,如<td>test</td>
,div.innerHTML,DOMParser.parseFromString和range.createContextualFragment(没有正确的上下文)解决方案在此处的其他答案中提到,将不会创建<td>
元素。
jQuery.parseHTML()正确处理它们(我提取了可以在非jquery代码库中使用的jQuery 2's parseHTML function into an independent function)。
如果您只支持Edge 13+,则只需使用HTML5模板标记即可:
function parseHTML(html) {
var t = document.createElement('template');
t.innerHTML = html;
return t.content.cloneNode(true);
}
var documentFragment = parseHTML('<td>Test</td>');
使用Prototype,您还可以:
HTML:
<ul id="mylist"></ul>
JS:
$('mylist').insert('<li>text</li>');
您可以使用以下命令从字符串创建有效的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);