web-dev-qa-db-ja.com

組み込みDOMメソッドまたはPrototypeを使用してHTML文字列から新しいDOM要素を作成する

要素を表すHTML文字列があります:'<li>text</li>'。 DOMの要素に追加したいのですが(私の場合はul)。 PrototypeまたはDOMメソッドでこれを行うにはどうすればよいですか?

(私はこれをjQueryで簡単にできることを知っていますが、残念ながら私たちはjQueryを使っていません。)

494
Omer Bokhari

注:現在のほとんどのブラウザはHTML <template>要素をサポートしています。これにより、文字列から要素を作成するより信頼性の高い方法が提供されます。 詳細については、以下のマークアメリーの回答 を参照してください。

古いブラウザ、およびnode/jsdom:(執筆時点ではまだ<template>要素をサポートしていません)では、次の方法を使用します。これは、HTML文字列からDOM要素を取得するためにライブラリが使用するものと同じです( 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テンプレートとは異なり、このは、<div>sのような<td>の子に合法的にできないいくつかの要素では機能しません

すでにライブラリを使用している場合は、ライブラリで承認されたHTML文字列から要素を作成する方法に従うことをお勧めします。

732
Crescent Fresh

HTML 5では、この目的に使用できる<template>要素が導入されました( WhatWG仕様 および MDN docs に記載されています)。

<template>は、他の要素型を子として許可されているHTML要素です。 template.contentプロパティを持っていて、JavaScriptでアクセスすることができます。これはテンプレートの内容で DocumentFragment を指します。これは、<template>要素の innerHTML を設定して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>');

divのような別のコンテナ要素を使用する同様のアプローチは - 全くうまくいきません。 HTMLでは、どの要素タイプを他のどの要素タイプの内部に存在させることができるかについて制限があります。たとえば、tddivの直接の子として置くことはできません。 innerHTMLdivをそれらを含むように設定しようとすると、これらの要素は消えます。 <template>sはその内容にそのような制限がないので、この欠点はテンプレートを使用するときには当てはまりません。

ただし、templateは一部の古いブラウザではサポートされていません。 2018年1月現在、 使用できますか? 概算 全世界の90%のユーザーがtemplatesをサポートするブラウザを使用しています 。特に、Internet Explorerのどのバージョンもそれらをサポートしていません。 MicrosoftはEdgeのリリースまでtemplateサポートを実装しませんでした。

最近のブラウザでユーザーを対象としたコードを書いているだけなら幸運なら、今すぐにそれらを使ってください。それ以外の場合は、ユーザーが追いつくまでしばらく待つ必要があります。

236
Mark Amery

insertAdjacentHTML() を使用します。 IE11でも、現在のすべてのブラウザで動作します。

var mylist = document.getElementById('mylist');
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
<ul id="mylist">
 <li>first</li>
 <li>second</li>
</ul>
58

新しい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
24
kojiro

微調整は必要ありません。ネイティブAPIが用意されています。

const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes
17
math2001

簡単な方法は次のとおりです。

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);
15
william malo

<td>test</td>、div.innerHTML、DOMParser.parseFromString、range.createContextualFragment(正しいコンテキストなし)のような特定のHTMLフラグメントについては、ここで他の回答で言及されていますが、<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>');
11
Munawwar

Prototypeを使えば、次のこともできます。

HTML:

<ul id="mylist"></ul>

JS:

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

以下を使用して文字列から有効な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);
7
GibboK

私はこのメソッドを使っています(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>
5
usrbowe

文字列から要素を作成するDocumentプロトタイプを追加しました。

Document.prototype.createElementFromString = function (str) {
    const element = new DOMParser().parseFromString(str, 'text/html');
    const child = element.documentElement.querySelector('body').firstChild;
    return child;
};
3
Raza

さまざまな場所で見つけることができる便利な.toDOM()スニペットをさらに強化するために、安全 use backticks テンプレートリテラル ) 。

そのため、foo html宣言では一重引用符と二重引用符を使用できます。

これは heredocs のように振る舞います。

これは変数でさらに強化することができ、複雑なテンプレートを作ることができます。

テンプレートリテラルは、二重引用符または一重引用符ではなく、バックティック()(Graveアクセント)文字で囲まれています。テンプレートリテラルにはプレースホルダーを含めることができます。これらはドル記号と中括弧($ {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}

https://caniuse.com/template-literals

2
Cryptopat

遅くてもメモとして。

簡単な要素をコンテナとしてターゲット要素に追加し、使用後にそれを削除することは可能です。

//クロム23.0、Firefox 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>
2
K-Gun

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>
1
xgqfrms-gildata

これが私のコードです、そしてそれはうまくいきます:

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

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

そのため、私はこれを私が思い付いた複雑ではあるが単純なアプローチで共有したいと思いました。

/*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')"
}));
0
JxAxMxIxN

var msg = "test" jQuery.parseHTML(msg)

0
nitish kumar