Ome*_*ari 555 javascript dom prototypejs
我有一个表示元素的HTML字符串:'<li>text</li>'
.我想将它附加到DOM中的一个元素(ul
在我的例子中).如何使用Prototype或DOM方法执行此操作?
(我知道我可以在jQuery中轻松完成这个,但不幸的是我们没有使用jQuery.)
Cre*_*esh 757
注意:大多数当前浏览器都支持HTML <template>
元素,这提供了一种更可靠的方法来转换从字符串创建元素.有关详细信息,请参阅Mark Amery的答案.
对于较旧的浏览器和node/jsdom :( <template>
在编写时尚不支持元素),请使用以下方法.图书馆用来从HTML字符串中获取DOM元素也是一样的(IE的一些额外工作可以解决bug的实现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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,与HTML模板这不会对某些元素不能合法的儿童工作<div>
,如<td>
秒.
如果您已经在使用库,我建议您坚持使用库批准的方法从HTML字符串创建元素:
update()
方法中内置了此功能.jQuery(html)
和jQuery.parseHTML
方法中实现了它.Mar*_*ery 288
HTML 5引入了<template>
可用于此目的的元素(现在在WhatWG规范和MDN文档中描述).
A <template>
是一个HTML元素,允许任何其他元素类型作为子元素.该template
有一个.content
,你可以用JavaScript,它指向一个访问属性DocumentFragment
与模板的内容.这意味着,你可以通过设置一个HTML字符串转换为DOM元素innerHTML
a的<template>
元素,然后伸到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 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>');
Run Code Online (Sandbox Code Playgroud)
请注意,使用不同容器元素的div
类似方法(例如a)不太起作用.HTML限制了允许哪些元素类型存在于哪些元素类型中; 例如,你不能把a td
作为直接的孩子div
.如果您尝试设置innerHTML
a div
来包含它们,这会导致这些元素消失.由于<template>
s对其内容没有这样的限制,因此在使用模板时这个缺点不适用.
但是,template
某些旧版浏览器不支持.截至2018年1月,我可以使用...估计全球90%的用户正在使用支持template
s 的浏览器.特别是,没有版本的Internet Explorer支持它们; template
在Edge发布之前,Microsoft没有实现支持.
如果您足够幸运能够编写仅针对现代浏览器用户的代码,请立即使用它们.否则,您可能需要等待一段时间才能让用户赶上.
Chr*_*use 89
使用insertAdjacentHTML().它适用于所有当前的浏览器,即使使用IE11.
var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
Run Code Online (Sandbox Code Playgroud)
<ul id="mylist">
<li>first</li>
<li>second</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
koj*_*iro 26
较新的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
Run Code Online (Sandbox Code Playgroud)
mat*_*001 18
无需任何调整,您有一个原生API:
const toNodes = html =>
new DOMParser().parseFromString(html, 'text/html').body.childNodes
Run Code Online (Sandbox Code Playgroud)
wil*_*alo 16
这是一个简单的方法:
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);
Run Code Online (Sandbox Code Playgroud)
Mun*_*war 15
对于某些html片段,例如<td>test</td>
div.innerHTML,DOMParser.parseFromString和range.createContextualFragment(没有正确的上下文)将不会创建<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>');
Run Code Online (Sandbox Code Playgroud)
Raz*_*aza 11
我添加了一个Document
从字符串创建元素的原型:
Document.prototype.createElementFromString = function (str) {
const element = new DOMParser().parseFromString(str, 'text/html');
const child = element.documentElement.querySelector('body').firstChild;
return child;
};
Run Code Online (Sandbox Code Playgroud)
用法:
document.createElementFromString("<h1>Hello World!</h1>");
Run Code Online (Sandbox Code Playgroud)
使用Prototype,您还可以:
HTML:
<ul id="mylist"></ul>
Run Code Online (Sandbox Code Playgroud)
JS:
$('mylist').insert('<li>text</li>');
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令从字符串创建有效的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);
Run Code Online (Sandbox Code Playgroud)
小智 7
为什么不用原生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;
Run Code Online (Sandbox Code Playgroud)
Template
Template's
innerHTML设置为您的string
.trim()
Array
的Template's
儿童children
, child
, 或
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>'));
Run Code Online (Sandbox Code Playgroud)
我正在使用此方法(在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>
Run Code Online (Sandbox Code Playgroud)
为了进一步增强我们可以在不同地方找到的有用的.toDOM()片段,我们现在可以安全地使用反引号(模板文字)。
所以我们可以在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 literals
var a = 10, b = 5
var foo=`
<img
onclick="alert('The future starts today!')"
src='//placekitten.com/100/100'>
foo${a + b}
<i>bar</i>
<hr>`.toDOM();
document.body.appendChild(foo);
Run Code Online (Sandbox Code Playgroud)
img {cursor: crosshair}
Run Code Online (Sandbox Code Playgroud)
那么,为什么不直接使用.innerHTML +=
呢?通过这样做,整个 DOM 正在由浏览器重新计算,速度要慢得多。
https://caniuse.com/template-literals
解决方案- 适用于 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);
Run Code Online (Sandbox Code Playgroud)
或者你可以使用DOMParser
var doc = (new DOMParser).parseFromString(htmlString, "text/html");
doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);
console.log(doc);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
528263 次 |
最近记录: |