我有一个表示元素的HTML字符串:'<li>text</li>'。我想将其附加到DOM中的一个元素(ul以我为例)。如何使用Prototype或DOM方法做到这一点?
(我知道我可以在jQuery中轻松地做到这一点,但不幸的是我们没有使用jQuery。)
var nodes = document.fromString("<b>Hello</b> <br>");
                我有一个表示元素的HTML字符串:'<li>text</li>'。我想将其附加到DOM中的一个元素(ul以我为例)。如何使用Prototype或DOM方法做到这一点?
(我知道我可以在jQuery中轻松地做到这一点,但不幸的是我们没有使用jQuery。)
var nodes = document.fromString("<b>Hello</b> <br>");
                Answers:
注意:当前大多数浏览器都支持HTML <template>元素,HTML 元素提供了一种更可靠的方式来从字符串创建元素。有关详细信息,请参见下面的Mark Amery的答案。
对于较旧的浏览器和node / jsdom:(<template>在撰写本文时尚不支持元素),请使用以下方法。库用于从HTML字符串中获取DOM元素的操作是相同的(为IE实现,还需要一些额外的工作来解决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; 
}请注意,与HTML模板不同,这不适用于某些不能合法地作为a的子元素的元素<div>,例如<td>s。
如果您已经在使用库,建议您坚持使用库批准的从HTML字符串创建元素的方法:
update()方法中内置了此功能。jQuery(html)和jQuery.parseHTML方法中实现了它。createElementFromHTML 具有误导性,因为div.firstChild返回的a Node不是HTMLElementeg can node.setAttribute。从函数创建Element返回div.firstElementChild。
                    <div>包装我添加的HTML .innerHTML令人讨厌。我从来没有想过使用.firstChild。
                    div,并且输出是[object SVGSVGElement]在控制台日志为我提供正确的DOM元素的同时。我究竟做错了什么?
                    HTML 5引入了<template>可用于此目的的元素(如WhatWG规范和MDN文档中所述)。
甲<template>元件用于声明可以在脚本中使用的HTML的片段。元素在DOM中表示为HTMLTemplateElement,其.content属性为DocumentFragment类型,以提供对模板内容的访问。这意味着,你可以通过设置一个HTML字符串转换为DOM元素innerHTMLa的<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>');请注意,使用不同容器元素(例如容器)的div类似方法不太可行。HTML对允许哪些元素类型存在于其他元素类型中有限制;例如,您不能将a td作为的直接子对象div。这将导致这些元素,如果你尝试设置消失innerHTML的div遏制他们。以来<template> s对它们的内容没有任何限制,因此使用模板时此缺点不适用。
但是,template某些旧版浏览器不支持。截至2018年1月,我可以使用...估计全球90%的用户正在使用支持templates 的浏览器。特别是,没有版本的Internet Explorer支持它们。template直到Edge发行,Microsoft才实现支持。
如果您很幸运地编写了仅针对现代浏览器用户的代码,请立即使用它们。否则,您可能需要等待一段时间才能赶上用户。
html.trim内部HTML设置的内部解析而是通过内部解析来删除的空格。就我而言,它删除了textNode中重要的空间。:-(
                    使用insertAdjacentHTML()。它适用于当前所有浏览器,甚至IE11。
var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');<ul id="mylist">
 <li>first</li>
 <li>second</li>
</ul>insertAdjacentHTML适用于IE 4.0以后的所有浏览器。
                    innerHTML += ...是使用此方法对以前元素的引用仍然完整。
                    beforebegin,afterbegin,beforeend,afterend。请参阅MDN文章。
                    较新的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.2innerHTMLdiv的缺点类似。某些元素(如td)将被忽略,并且不会出现在结果片段中。
                    无需任何调整,您就获得了本机API:
const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes[0]<td>text</td>。这是因为DOMParser试图解析完整的HTML文档,并且并非所有元素都有效作为文档的根元素。
                    对于某些HTML片段,例如<td>test</td>div.innerHTML,DOMParser.parseFromString和range.createContextualFragment(没有正确的上下文),在本文其他答案中提到的解决方案将不会创建该<td>元素。
jQuery.parseHTML()正确地处理了它们(我将jQuery 2的parseHTML函数提取为一个可在非jquery代码库中使用的独立函数)。
如果仅支持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>');这是一种简单的方法:
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);您可以使用以下命令从字符串创建有效的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);DocumentFragment对象,但令我惊讶的是,它仍然遭受与公认答案相同的缺陷:如果这样做document.createRange().createContextualFragment('<td>bla</td>'),您将得到一个仅包含文本'bla'而不包含<td>元素的片段。至少,这就是我在Chrome 63中观察到的;我没有深入研究规范来确定它是否正确。
                    使用原型,您还可以执行以下操作:
HTML:
<ul id="mylist"></ul>JS:
$('mylist').insert('<li>text</li>');为了进一步增强我们可以在不同位置找到的有用的.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 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,速度要慢得多。
我添加了一个Document原型,该原型从字符串创建一个元素:
Document.prototype.createElementFromString = function (str) {
    const element = new DOMParser().parseFromString(str, 'text/html');
    const child = element.documentElement.querySelector('body').firstChild;
    return child;
};<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>迟了,但只是作为笔记;
可以向目标元素添加一个琐碎的元素作为容器,并在使用后将其删除。
//在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>从字符串呈现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};
};而这里 ü可以检查DOM操作的性能阵营VS本土JS
现在您可以简单地使用:
let element = render(document.body, `
<div style="font-size:120%;line-height:140%">
  <p class="bold">New DOM</p>
</div>
`);当然,在不久的将来,您会使用内存中的引用,因为var“ element”是您在文档中新创建的DOM。
并记住“ innerHTML =“非常慢:/
这是我的代码,它可以正常工作:
function parseTableHtml(s) { // s is string
    var div = document.createElement('table');
    div.innerHTML = s;
    var tr = div.getElementsByTagName('tr');
    // ...
}对于这个问题,我想我会分享我提出的复杂但简单的方法……也许有人会发现有用的东西。
/*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')"
}));为什么不使用本机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=range.createContextualFragment(s);
    e.appendChild(f);
    e = e.firstElementChild;您可以使用以下函数将文本“ 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);td。
                    这也将起作用:
$('<li>').text('hello').appendTo('#mylist');感觉更像是带有链接函数调用的jquery方式。