使用内置的DOM方法或Prototype从HTML字符串创建新的DOM元素

923
我有一个表示元素的HTML字符串:'<li>text</li>',我想将其附加到DOM中的一个元素(在我的情况下是一个ul)。我该如何使用Prototype或DOM方法来实现这一点?(我知道在jQuery中很容易做到这一点,但不幸的是我们没有使用jQuery。)

2
抱歉,您究竟想要实现什么目标?将HTML字符串转换为DOM元素? - Crescent Fresh
86
这些解决方案过于间接,这让人感到不幸。我希望标准委员会能够指定类似的规范,例如:“var nodes = document.fromString('<b>Hello</b> <br>');” - Sridhar Sarnobat
1
我遇到了一个问题,因为我有一些需要传递的属性,而我不想解析它们:"<table id='5ccf9305-4b10-aec6-3c55-a6d218bfb107' class='data-table row-border display' cellspacing='0' width='100%'></table>"所以,我只是使用了:$("<table id='5ccf9305-4b10-aec6-3c55-a6d218bfb107' class='data-table row-border display' cellspacing='0' width='100%'></table>") - stevenlacerda
30个回答

8

为什么不使用原生JavaScript?

    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;

1
迄今为止最好的答案。 - zardilior
惊人!!然后,一个人可以轻松地使用 node.appendChild(e) - bot19
当你意识到本地解决方案是最简单的时候,那一刻是无价的 ^_^ - Muhammad Ali
出于好奇,为什么这会比“insertAdjacentHTML”更受青睐? - NickW

6

回答

  • 创建一个Template
  • Template的innerHTML设置为您的字符串.trim()
  • 创建一个Template的子元素数组
  • 返回childrenchild

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


4

解决方案 - 可在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);

或者您可以使用DOMParser

var doc = (new DOMParser).parseFromString(htmlString, "text/html");
    doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);

console.log(doc);

4

HTML5 & ES6

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


4
以下是如何使用PrototypeJS(正如12年前的原始请求)完成此操作的方法:
HTML:
<ul id="mylist"></ul>

JS:

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

请注意这不是jQuery!

这是jQuery还是JS? - Jeya Suriya Muthumari
2
@JuanHurtado 这是使用PrototypeJs,正如OP在将近11年前所请求的那样 ;) - Pablo Borowicz
@PabloBorowicz 抱歉,你说得对。我的脑海里自动想到了“内置的dom方法”,而忽略了原型部分。 - Juan Hurtado

3

这是我的代码,它可以正常运行:

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

    var tr = div.getElementsByTagName('tr');
    // ...
}

1
如果要创建的元素本身就是一个表格,则失败。 - Mark Amery

3

晚了点,但是需要注意的是;

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

// 在chrome 23.0,firefox 18.0,ie 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>

3

最快的将字符串渲染为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操作的性能React vs native JS:https://jsperf.com/react-vs-raw-dom-manipulation

现在,您可以简单地使用:

let element = render(document.body, `
<div style="font-size:120%;line-height:140%">
  <p class="bold">New DOM</p>
</div>
`);

当然,在不久的将来,您可以使用从内存中引用的变量"element",因为它是您在文档中创建的新DOM。

请记住,"innerHTML="非常缓慢 :/


非常好的答案,谢谢。你没有更多关于这个主题的链接可以分享吗?比如深入探讨为什么它更快? - NickW

1

1

我自己也搜索了很多,找到了这个简洁的解决方案。

const stringToHTML = (str) => {
    var parser = new DOMParser();
    var doc = parser.parseFromString(str, 'text/html');
    return doc.body;
};

我想要转换的字符串:

'<iframe src="https://player.vimeo.com/video/578680903?h=ea840f9223&amp;app_id=122963" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen title="Total Body Balance"></iframe>'

结果:

<body><iframe src="https://player.vimeo.com/video/578680903?h=ea840f9223&amp;app_id=122963" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen="" title="Total Body Balance"></iframe></body>

只有我觉得初始化domparser、domdocument等等,仅仅为了生成一个单一节点有点滑稽吗?大多数选项都可以在createElement(iframe)上设置..这不是最具吸引力的用例.. ;) - Christoffer Bubach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接