Как правильно использовать innerHTML для создания элемента (с возможными дочерними элементами) из строки html? - PullRequest
21 голосов
/ 08 сентября 2010

Примечание: я НЕ хочу использовать любой фреймворк.

<ч />

Цель состоит в том, чтобы просто создать функцию, которая будет возвращать элемент на основе строки HTML.


Предположим, что простой HTML-документ выглядит так:

<html>
<head></head>
<body>
</body>
</html>

Все упомянутые функции включены в раздел head, и все создание / манипулирование DOM выполняется в конце тела в теге script.


У меня есть функция createElement, которая принимает правильно сформированную строку HTML в качестве аргумента. Это выглядит так:

function createElement(str)
{
  var div = document.createElement('div');
  div.innerHTML = str;
  return div.childNodes;
}

Теперь эта функция прекрасно работает, когда вы называете ее так:

var e = createElement('<p id="myId" class="myClass">myInnerHTML</p>');

С незначительной (возможно ОГРОМНОЙ) проблемой, что созданный элемент не является «истинным» элементом, он все еще имеет parentNode «div». Если кто-нибудь знает, как это исправить, это было бы замечательно.


Теперь, если я вызову ту же функцию с более сложной строкой:

var e = createElement('<p id="myId" class="myClass">innerHTML<h2 id="h2ID" class="h2CLASS">Heading2</h2></p>');

Он создает ДВУХ детей вместо ОДНОГО ребенка с другим ребенком, у которого есть другой ребенок.

Как только вы сделаете div.innerHTML = str. Внутренний HTML вместо

`<p id="myId" class="myClass">innerHTML    <h2 id="h2ID" class="h2CLASS">Heading2</h2>    </p>`

превращается в

`<p id="myId" class="myClass">innerHTML</p>        <h2 id="h2ID" class="h2CLASS">Heading2</h2>`

<ч /> Вопросы:

  1. Можно ли как-то получить элемент без родительского узла после использования .innerHTML?
  2. Могу ли я (в случае слегка сложной строки) заставить мою функцию возвращать ОДИН элемент с соответствующим дочерним элементом вместо двух элементов. [На самом деле возвращает три, <p.myClass#myId>, <h2.h2CLASS#h2ID> и еще один <p>]

Ответы [ 2 ]

14 голосов
/ 08 сентября 2010

Это похоже на ответ из palswim, за исключением того, что он не беспокоится о создании клона, а вместо этого использует цикл while(), всегда добавляя узел в [0].

function createElement( str ) {
    var frag = document.createDocumentFragment();

    var elem = document.createElement('div');
    elem.innerHTML = str;

    while (elem.childNodes[0]) {
        frag.appendChild(elem.childNodes[0]);
    }
    return frag;
}
3 голосов
/ 08 сентября 2010

Вы должны были бы присоединить новый элемент где-нибудь. Попробуйте использовать объект DocumentFragment в сочетании с созданным вами div:

function createElement(str) {
    var div = document.createElement('div');
    div.innerHTML = str;
    var container = document.createDocumentFragment();
    for (var i=0; i < div.childNodes.length; i++) {
        var node = div.childNodes[i].cloneNode(true);
        container.appendChild(node);
    }
    return container.childNodes;
}

Это больше накладных расходов, но оно делает то, что вы хотите. Обратите внимание, что функция-член .insertAdjacentHTML элементов DOM появилась в HTML5.

Для этой сложной строки, которую вы передали, недопустимый синтаксис XHTML - вы не можете иметь элемент блока в качестве дочернего элемента <p> (<h2> является элементом уровня блока).

...