Что такое DOM

DOM (Document Object Model) – это представление HTML-документа в виде дерева объектов.

JavaScript работает не напрямую с HTML, а с объектами DOM:

const div = document.createElement('div');
 
div.textContent = 'Hello';
 
document.body.appendChild(div);

Работа с DOM обычно состоит из трёх этапов:

  1. Создать элемент
  2. Настроить его
  3. Добавить в документ

Создание элементов

document.createElement()

Создаёт новый HTML-элемент.

const div = document.createElement('div');

После создания элемент существует только в памяти:

const button = document.createElement('button');
 
button.textContent = 'Click';

Чтобы он появился на странице, нужно добавить его в DOM:

document.body.appendChild(button);

document.createTextNode()

Создаёт отдельный текстовый узел.

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

Используется реже, потому что обычно проще:

element.textContent = 'Hello';

Добавление элементов

appendChild()

Добавляет элемент в конец списка дочерних элементов.

parent.appendChild(child);

Пример:

const p = document.createElement('p');
 
div.appendChild(p);

Результат:

<div>
	<p></p>
</div>

prepend()

Добавляет элемент в начало.

div.prepend(p);

Было:

<div>
	<span></span>
</div>

Стало:

<div>
	<p></p>
	<span></span>
</div>

insertBefore()

Вставляет элемент перед другим элементом.

parent.insertBefore(
	newNode,
	referenceNode
);

Пример:

div.insertBefore(newDiv, div.firstChild);

before() / after()

Современный способ вставки относительно элемента.

Перед элементом:

element.before(node);

После элемента:

element.after(node);

Пример:

p.before(span);
p.after(button);

Удаление элементов

remove()

Удаляет элемент напрямую.

element.remove();

Пример:

div.remove();

removeChild()

Удаляет дочерний элемент через родителя.

parent.removeChild(child);

Пример:

div.removeChild(p);

replaceChild()

Заменяет один элемент другим.

parent.replaceChild(
	newChild,
	oldChild
);

Пример:

div.replaceChild(newDiv, oldDiv);

Атрибуты и классы

Атрибуты

setAttribute()

Добавляет или изменяет атрибут.

element.setAttribute(
	'name',
	'value'
);

Пример:

img.setAttribute(
	'src',
	'image.png'
);

getAttribute()

Получает значение атрибута.

img.getAttribute('src');

removeAttribute()

Удаляет атрибут.

img.removeAttribute('src');

Работа с классами

className

Полностью заменяет строку классов.

div.className = 'card large';

Минус:

div.className = 'active';

Удалит все предыдущие классы.

classList

Работа с отдельными классами.
Добавить:

element.classList.add('active');

Удалить:

element.classList.remove('active');

Переключить:

element.classList.toggle('hidden');

Работа с текстом и HTML

textContent

Работа с обычным текстом.

div.textContent = 'Hello';

Безопаснее, чем innerHTML.

innerHTML

Работа с HTML-разметкой.

div.innerHTML = `
	<span>Hello</span>
`;

Особенность:
innerHTML полностью пересоздаёт содержимое элемента.

Это значит:

div.innerHTML = '<button>OK</button>';

может удалить ранее добавленные обработчики событий.

innerText

Работает только с видимым текстом.

div.innerText = 'Hello';

Отличие:
textContent – берёт весь текст из DOM
innerText – учитывает CSS и отображение

Поиск элементов

querySelector()

Возвращает первый найденный элемент.

document.querySelector('.card');

Работает с CSS-селекторами:

document.querySelector(
	'#app .button'
);

querySelectorAll()

Возвращает все совпадения.

document.querySelectorAll('.card');

Старые методы поиска

По ID

document.getElementById('root');

По классу

document.getElementsByClassName('card');

По тегу

document.getElementsByTagName('div');

События

addEventListener()

Основной способ подписки на события.

button.addEventListener(
	'click',
	() => {
		alert('Hi');
	}
);

Плюсы:

  • можно добавить несколько обработчиков;
  • можно удалить;
  • работает с любыми событиями.

removeEventListener()

Удаляет обработчик.

button.removeEventListener(
	'click',
	handler
);

onclick

Быстрая запись:

button.onclick = () => {
	alert('Hi');
};

Минус:

button.onclick = fn1;
button.onclick = fn2;

fn1 будет заменён.

Размеры и положение

offsetWidth / offsetHeight

Размер элемента вместе с:

  • padding;
  • border.

clientWidth / clientHeight

Размер без границ.

getBoundingClientRect()

Возвращает координаты элемента:

const rect =
	element.getBoundingClientRect();

Результат:

{
	top,
	left,
	width,
	height
}

Используется для:

  • drag & drop;
  • позиционирования;
  • анимаций.

Другие полезные методы

cloneNode()

Клонирует элемент.

const copy = element.cloneNode(true);

true → копировать вместе с детьми.

contains()

Проверяет вложенность.

parent.contains(child);

scrollIntoView()

Прокручивает страницу к элементу.

element.scrollIntoView();

Паттерн создания динамических списков

Частый сценарий:

  1. Есть массив данных.
  2. Создаём DOM-элемент.
  3. Заполняем данными.
  4. Добавляем в страницу.
const list = document.createElement('div');
 
tasks.forEach(task => {
	const item = document.createElement('div');
 
	item.textContent = task.title;
 
	list.appendChild(item);
});
 
root.appendChild(list);

Главное правило работы с DOM

Массив данных → создание DOM → настройка → вставка в документ

Большинство динамических интерфейсов строятся именно по этой схеме.

🔗 Связано