На этом уроке мы научимся создавать узлы-элементы (createElement) и текстовые узлы (createTextNode). А также рассмотрим методы, предназначенные для добавления узлов к дереву (appendChildinsertBefore) и для удаления узлов из дерева (removeChild).

Создания элементов и текстовых узлов

Создание элемента в JavaScript выполняется с помощью метода createElement:

// elem = document.createElement(‘tag’);`

Вместо tag необходимо указать тег того элемента, который нужно создать.

Например, создадим элемент p: const $elem = document.createElement('p');

Создание текстового узла в JavaScript осуществляется посредством метода createTextNode:

const text = document.createTextNode('text');

В аргументе createTextNode необходимо поместить текст, который должен иметь этот текстовый узел.

Например, создадим текстовый узел с текстом «Я новый текстовый узел»: const text = document.createTextNode('Я новый текстовый узел');

Вставка элементов и текстовых узлов

Чтобы созданный элемент (или текстовый узел) появился в нужном месте страницы его необходимо туда вставить.

Выполнить в JavaScript это можно посредством различных методов. Одни из самых старых – appendChild и insertBefore.

appendChild

appendChild предназначен для вставки узла в конец элемента (т.е. после последнего его дочернего узла) для которого этот метод вызывается:

// node node);

В качестве результата этот метод возвращает добавленный на страницу узел. Пример, в котором добавим новый <li> в конец <ol>:

<ol id="colors">
  <li>Красный</li>
  <li>Оранжевый</li>
  <li>Жёлтый</li>
  <li>Зелёный</li>
  <li>Голубой</li>
  <li>Синий</li>
</ol>
 
<script>
  const $newLi = document.createElement("li");
  $newLi.textContent = "Фиолетовый";
  const $colors = document.querySelector("#colors");
  $colors.appendChild($newLi);
</script>

insertBefore

insertBefore предназначен для вставки узла node перед nextSibling в $elem:

$elem.insertBefore(node, nextSibling);

Если в качестве nextSibling передать null, то данный метод вставит node после последнего дочернего узла $elem. Т.е. выполнит действия аналогично appendChild.

В качестве результата метод insertBefore “возвращает вставленный узел.

Например, вставим новый элемент <li> перед третьим:

<ol id="colors">
  <li>Красный</li>
  <li>Оранжевый</li>
  <li>Зелёный</li>
  <li>Голубой</li>
  <li>Синий</li>
  <li>Фиолетовый</li>
</ol>
 
<script>
  const $newLi = document.createElement("li");
  $newLi.textContent = "Жёлтый";
  const $colors = document.querySelector("#colors");
  $colors.insertBefore($newLi, $colors.children[2]);
</script>

Современные“ методы вставки и замены

В JavaScript имеются следующие современные методы для вставки элементов и строк:

  • node.append – для добавления узлов или строк в конец node;
  • node.prepend – для вставки узлов или строк в начало node;
  • node.before – для вставки узлов или строк до node;
  • node.after – для вставки узлов или строк после node.

Пример использования методов:

<div id="message">
  <p>message...</p>
</div>
 
<script>
  const $message = document.querySelector("#message");
 
  // вставим строку «before» перед $message
  $message.before("before");
 
  // вставим строку «after» перед $message
  $message.after("after");
 
  const $p1 = document.createElement("p");
  $p1.textContent = "prepend";
  // вставим элемент $p1 в начало $message
  $message.prepend($p1);
 
  const $p2 = document.createElement("p");
  $p2.textContent = "append";
 
  // вставим элемент $p2 в конец $message
  $message.append($p2);
</script>

В результате:

before
<div id="message">
  <p>prepend</p>
  <p>message...</p>
  <p>append</p>
</div>
after

InsertAdjacent

В JavaScript имеется набор методов insertAdjacent, которые позволяют вставить один или несколько узлов в указанную позицию position относительно $elem

Всего существует 3 таких метода:

  • $elem.insertAdjacentElement(position, element) – для вставки элемента (element);
  • $elem.insertAdjacentHTML(position, htmlString) – для вставки строки (htmlString) как HTML;
  • $elem.insertAdjacentText(position, string) – для вставки строки (string);

Значение position, может быть, одним из следующих:

  • 'beforebegin' – непосредственно перед $elem;
  • 'afterbegin' – перед первым дочерним узлом $elem;
  • 'beforeend' – после последнего дочернего узла $elem;
  • 'afterend' – сразу после $elem;

Пример использования insertAdjacentHTML:

<ul id="list">
  <li>CSS</li>
</ul>
 
<script>
  const $list = document.querySelector("#list");
 
  $list.insertAdjacentHTML("beforebegin", "<h2>Веб-технологии</h2>");
  $list.insertAdjacentHTML("afterbegin", "<li>HTML</li>");
  $list.insertAdjacentHTML("beforeend", "<li>JavaScript</li>");
  $list.insertAdjacentHTML("afterend", "<p>Для фронтенд разработчиков</p>");
</script>

Результат:

<h2>Веб-технологии</h2>
<!-- beforebegin -->
<ul id="list">
  <!-- целевой элемент -->
  <li>HTML</li>
  <!-- afterbegin -->
  <li>CSS</li>
  <li>JavaScript</li>
  <!-- beforeend -->
</ul>
<p>Для фронтенд разработчиков</p>
<!-- afterend -->

DocumentFragment

DocumentFragment – это облегчённая версия Document. Он используется в качестве обёртки для временного хранения HTML элементов.

После формирования фрагмента его можно использовать в различных методах (например, appendprepend и др.). При этом, когда мы его вставляем, то вставляется только его содержимое.

DocumentFragment в основном используется, когда необходимо вставить множество элементов на страницу, а также для элемента <template>.

Например, переместим все четные <li> в новый <ul>:

<ul id="source-list">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
  <li>Four</li>
</ul>
    ```html ```

    Ещё один пример, в котором добавим в <ul> десять <li>:

    <ul id="list"></ul>
     
    <script>
      const $list = document.querySelector("#list");
      // создадим пустой фрагмент
      let $fragment = new DocumentFragment();
      for (let i = 0; i < 10; i++) {
        const $li = document.createElement("li");
        $li.textContent = "item-" + i;
        // добавим в фрагмент элемент $li
        $fragment.appendChild($li);
      }
      // вставим фрагмент в #target-list
      document.querySelector("#list").append($fragment);
    </script>

    Использование DocumentFragment в подобных сценариях может значительно ускорить ваш сайт. Т.к. изменение DOM — это очень затратная операция. А с помощью DocumentFragment это можно сделать всего за одну операцию.

    DocumentFragment не является частью видимой DOM. Изменения, внесенные во фрагмент, не влияют на документ и производительность страницы.

    При использовании современных методов для вставки элементов можно не использовать DocumentFragment, т.к. в отличие от appendChild и insertBefore они позволяют вставлять сразу массив элементов.

    Например, перепишем первый пример с использованием append:

    <ul id="source-list">
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
      <li>Four</li>
    </ul>
     
    <ul id="target-list"></ul>
     
    <script>
      const $evenLi = document.querySelectorAll("#source-list li:nth-child(even)");
      // создадим пустой массив
      let $list = [];
      $evenLi.forEach(($li) => {
        // добавим в массив $target элемент $li
        $list.appendChild($li);
      });
      // вставим массив элементов в #target-list
      document.querySelector("#target-list").append(...$list);
    </script>

    Замена и клонирование узлов

    Замену одних узлов другими в JavaScript можно выполнить с помощью методов replaceChild (когда нужна поддержка «старых» браузеров) и replaceWith.

    replaceChild

    replaceChild предназначен для замены одного дочернего узла parentNode другим:

    parentNode.replaceChild(newChild, oldChild);

    Где:

    • newChild – элемент, которым необходимо заменить oldChild;
    • parentNode – родительский узел по отношению oldChild.

    В качестве результата данный метод возвращает узел, который был заменён новым узлом, т.е. oldChild.

    Например, заменим в <ul> второй <li> на новый с текстом «Five».

    ul id="list">
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
    </ul
     
    <script>
      $two = document.querySelector('#list li:nth-child(2)');
      // создадим новый элемент
      $newLi = document.createElement('li');
      $newLi.textContent = 'Five';
      // заменим $two на $newLi $two.parentNode.replaceChild($newLi, $two);
    </script>

    replaceWith

    node.replaceWith позволяет node заменить заданными узлами или строками:

    node.replaceWith(...nodes, strings)

    Например, заменим в <ul> второй <li> другими элементами:

    ul id="list">
      <li>One</li>
      <li>Two</li>
      <li>Three</li>
    </ul
     
    <script>
      $two = document.querySelector('#list li:nth-child(2)');
      // создадим новые элементы
      $newLi1 = document.createElement('li');
      $newLi1.textContent = 'Five';
      $newLi2 = document.createElement('li');
      $newLi2.textContent = 'Six';
      // заменим $two на $newLi1 и $newLi2
      $two.replaceWith($newLi1, $newLi2);
    </script>

    cloneNode – клонирование узла

    cloneNode предназначен для создания копии узла:

    let copy = node.cloneNode(deep);

    Где:

    • node – узел, который нужно клонировать;
    • copy – переменная, в которую нужно поместить новый узел, который будет копией node;
    • deep – глубина клонирования (по умолчанию false, т.е. выполняется клонирование только самого элемента node без детей); если установить true, то node будет скопирован со всеми его детьми.

    Например, скопируем ul> и вставим её в конец body.

    ul id="list">
      <li>One</li>
      ...
    </ul
     
    <script>
      // выбираем #list
      const $list = document.querySelector('#list');
      // клонируем $list и помещает его в $copy
      const $copy = $list.cloneNode(true);
      // вставляем $copy в конец <body>
      document.body.append($copy);
    </script>

    Удаление узлов

    Удалить узел из DOM можно в JavaScript с помощью методов removeChild (считается устаревшим) и remove.

    removeChild

    Синтаксис removeChild:

    parent.removeChild(node)

    Для удаления узла необходимо вызвать метод removeChild у родительского элемента и передать ему в качестве аргумента его сам (node).

    Например, удалим второй <li> в <ol>:

    <ol id="devices">
      <li>Смартфон</li>
      <li>Планшет</li>
      <li>Ноутбук</li>
    </ol>
    <script>
      const $liSecond = document.querySelector("#devices li:nth-child(2)");
      // вызываем у родительского элемента метод removeChild и передаём ему в качестве аргумента узел который нужно удалить
      $liSecond.parentNode.removeChild($liSecond);
    </script>

    В качестве результата метод removeChild возвращает удалённый узел.

    Например, удалим элемент, а затем вставим его в другое место:

    <div id="message-1">
      <p>...</p>
    </div>
     
    <div id="message-2"></div>
     
    <script>
      const $p = document.querySelector("#message-1>p");
      // удалим элемент p
      const result = $p.parentElement.removeChild($p);
      // вставим удалённый элемент p в #message-2
      document.querySelector("#message-2").append(result);
    </script>

    remove

    Ещё один способ удалить узел – это использовать метод remove.

    Синтаксис remove:

    node.remove()

    Например, удалим элемент при нажатии на него: “

    <button>Кнопка</button>
    <script>
      document.querySelector("button").onclick = function () {
        // удалим элемент
        this.remove();
      };
    </script>

    Когда мы вставляем элементы, они удаляются со старых мест.