Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Манипулирование DOM-деревом JS: DOM API

DOM-дерево может изменяться, когда браузер уже выполнил его рендеринг. Именно этот факт позволяет создавать интерактивные приложения.

В этом уроке мы обсудим, как манипулировать DOM-деревьями и какие преимущества мы можем при этом получить.

innerHTML

Самый простой способ обновить часть DOM — это свойство innerHTML:

<ul>
  <li>item 1</li>
  <li>item 2</li>
</ul>
const body = document.body;
console.log(body);
// <ul><li>item 1</li><li>item 2</li></ul>

body.innerHTML = '<b>make</b> love';
console.log(body.innerHTML);
// <b>make</b> love

console.log(body.childNodes);
// [b, text]

Значение этого свойства полностью заменяет потомков элемента, на котором мы его вызвали. Весь HTML, находящийся внутри, анализируется и становится частью дерева.

Представьте, что мы пытаемся вставить обычный текст, в котором потенциально содержится HTML. Это повышает вероятность XSS-атак, поэтому мы должны использовать другое свойство - textContent.

Свойство textContent работает практически идентично, оно также заменяет всех потомков. Основное различие между этими свойствами заключается в том, что textContent рассматривает содержимое как обычный текст в любом случае, даже если там есть HTML:

document.body.textContent = '<b>make</b> love';
console.log(document.body.innerHTML);
// Все специальные символы оказываются замененными
// "&lt;b&gt;make&lt;/b&gt; love"

Свойство innerHTML работает со строками. Это удобно, только если мы работаем со статическим представлением DOM. Для динамического формирования хорошо подходят специальные функции.

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

// Создаем текстовый узел
const textNode = document.createTextNode('life is life');

// Создаем элемент p
const pEl = document.createElement('p');

// Добавляем textNode в конец списка childNodes элемента pEl
pEl.append(textNode);
// pEl.textContent = 'life is life';

const el = document.createElement('div');
el.append(pEl);

console.log(el);
// <div><p>life is life</p></div>

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

Вставка

ParentNode.prepend() добавляет переданный узел первым потомком в ParentNode:

const div = document.createElement('div');
div.innerHTML = '<span>Hexlet</span>';

const el = document.createElement('p');
el.textContent = 'prepend';
div.prepend(el);
// <div>
//   <p>prepend</p>
//   <span>Hexlet</span>
// </div>

ParentNode.append() добавляет переданный узел последним потомком в ParentNode:

const div = document.createElement('div');
div.innerHTML = '<span>Hexlet</span>';

const el = document.createElement('p');
el.textContent = 'append';
div.append(el);
// <div>
//   <span>Hexlet</span>
//   <p>append</p>
// </div>

childNode.before(...nodes) – вставляет nodes в список потомков родительского узла childNode прямо перед childNode:

const div = document.createElement('div');
div.innerHTML = '<span>Hexlet</span>';
// Должен быть вставлен в DOM-дерево
document.body.append(div);

const el = document.createElement('p');
el.textContent = 'content';
div.before(el);
// <p>content</p>
// <div>
//   <span>Hexlet</span>
// </div>

childNode.after(...nodes) – вставляет nodes в список потомков родительского узла childNode сразу после childNode:

const div = document.createElement('div');
div.innerHTML = '<span>Hexlet</span>';
// Должен быть вставлен в DOM-дерево
document.body.append(div);

const el = document.createElement('p');
el.textContent = 'content';
div.after(el);
// <div>
//   <span>Hexlet</span>
// </div>
// <p>content</p>

node.replaceWith(...nodes) – вставляет nodes вместо node. Сама node пропадает из DOM-дерева, но остается доступной в коде:

const div = document.createElement('div');
div.innerHTML = '<span>Hexlet</span>';
// Должен быть вставлен в DOM-дерево
document.body.append(div);

const el = document.createElement('p');
el.textContent = 'content';
div.replaceWith(el);
// В DOM-дереве вместо div остался p
// <p>content</p>

Element.remove() удаляет текущий узел.

Создание элемента не добавляет сразу этот элемент на страницу. Например, document.createElement('div') просто создаст объект элемента div. При этом этот объект не будет частью DOM-дерева. Поэтому нужно вставить этот объект в дерево, если нужно добавить его на страницу.

Старый API

Описанные выше функции появились не так давно. Большая часть кода написана с использованием других функций, список которых ниже:

  • parent.appendChild(el) – добавляет el в конец списка потомков
  • parent.insertBefore(el, nextElSibling) – добавляет el в список потомков parent перед nextElSibling
  • parent.removeChild(el) – удаляет el из потомков parent
  • parent.replaceChild(newEl, el) – заменяет el на newEl

Клонирование

Иногда нам нужно создать элемент, похожий на существующий. Конечно, это можно сделать вручную, скопировав свойства одного элемента в свойства другого. Но есть и более простой способ:

const newEl = el.cloneNode(true);

Значение true показывает, что мы создаем глубокую копию — то есть копию данного элемента со всеми его потомками.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 18 апреля
профессия
от 9 900 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 18 апреля
профессия
новый
Автоматизированное тестирование веб-приложений на JavaScript
8 месяцев
c опытом
в разработке
Старт 18 апреля

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»