[javascript] 내장 DOM 메소드 또는 프로토 타입을 사용하여 HTML 문자열에서 새 DOM 요소 작성

요소를 나타내는 HTML 문자열이 '<li>text</li>'있습니다. DOM의 요소 ( ul내 경우에는 a) 에 추가하고 싶습니다 . 프로토 타입 또는 DOM 메소드를 사용하여이를 수행하려면 어떻게해야합니까?

(jQuery 에서이 작업을 쉽게 수행 할 수 있다는 것을 알고 있지만 불행히도 우리는 jQuery를 사용하지 않습니다.)



답변

참고 : 대부분의 최신 브라우저는 HTML <template>요소를 지원 하므로 문자열에서 요소를보다 안정적으로 만들 수 있습니다. 자세한 내용은 아래 Mark Amery의 답변을 참조하십시오 .

이전 브라우저 및 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 템플릿과 달리 s 와 같은 합법적으로 자식이 될 수없는 일부 요소 에는 작동하지 않습니다 .<div><td>

이미 라이브러리를 사용하고 있다면 HTML 문자열에서 요소를 만드는 라이브러리 승인 방법을 따르는 것이 좋습니다.


답변

HTML 5는 <template>이 목적으로 사용할 수있는 요소를 도입했습니다 (현재 WhatWG 사양MDN 문서에 설명되어 있음 ).

<template>소자 스크립트에서 사용될 수 HTML 단편을 선언하기 위해 사용된다. 요소는 템플릿의 컨텐츠에 대한 액세스를 제공하기 위해 DOM 에서 유형 HTMLTemplateElement.content특성 을 갖는 것으로 표시됩니다 DocumentFragment. 당신이 설정하여 DOM 요소에 HTML 문자열을 변환 할 수있는이 수단 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>');

다른 컨테이너 요소div사용하는 유사한 접근 방식은 작동하지 않습니다. HTML에는 어떤 요소 유형이 어떤 다른 요소 유형 내에 존재할 수 있는지에 대한 제한이 있습니다. 예를 들어을 td의 직계 자식으로 사용할 수 없습니다 div. innerHTMLa div를 포함 하도록 설정하면 이러한 요소가 사라집니다 . 이후 <template>의 해당 콘텐츠에 이런 제한이 없습니다 템플릿을 사용하는 경우, 이러한 단점이 적용되지 않습니다.

그러나 template일부 이전 브라우저에서는 지원되지 않습니다. 2018 년 1 월 기준으로 사용할 수 있습니까 … 전 세계 사용자의 90 %가 templates 를 지원하는 브라우저를 사용하고 있다고 추정 합니다 . 특히 어떤 버전의 Internet Explorer도 지원하지 않습니다. Microsoft는 templateEdge가 릴리스 될 때까지 지원을 구현하지 않았습니다 .

최신 브라우저 사용자만을 대상으로하는 코드를 작성하기에 운이 좋으면 지금 바로 사용하십시오. 그렇지 않으면 사용자가 따라 잡기까지 잠시 기다려야 할 수도 있습니다.


답변

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[0]


답변

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


답변

간단한 방법은 다음과 같습니다.

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