← Назад к вопросам

Для чего используется DOM?

1.0 Junior🔥 111 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Использование DOM (Document Object Model)

DOM (Document Object Model) — это программный интерфейс для работы с HTML и XML документами. Он представляет структуру документа в виде иерархического дерева объектов, позволяя скриптам (обычно JavaScript) читать, изменять и удалять элементы страницы.

Основное назначение DOM

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

  1. Манипуляция структурой страницы — добавление, удаление, изменение элементов
  2. Изменение стилей — динамическое применение CSS
  3. Обработка событий — реакция на клики, вводы, скроллы и т.д.
  4. Получение данных — чтение значений из форм и элементов
  5. Создание интерактивности — динамическое обновление содержимого без перезагрузки

Структура DOM

DOM представляет HTML как дерево:

<!DOCTYPE html>
<html>
  <head>
    <title>Пример</title>
  </head>
  <body>
    <div id="main">
      <p class="text">Привет</p>
      <button>Нажми меня</button>
    </div>
  </body>
</html>

В памяти браузера это выглядит как дерево объектов:

Document
  ├── html (HTMLElement)
  │   ├── head (HTMLElement)
  │   │   └── title (HTMLElement) "Пример"
  │   └── body (HTMLElement)
  │       └── div#main (HTMLElement)
  │           ├── p.text (HTMLElement) "Привет"
  │           └── button (HTMLElement) "Нажми меня"

API для работы с DOM

Выбор элементов:

// По ID
const element = document.getElementById('main');

// По селектору
const para = document.querySelector('p.text');
const allParas = document.querySelectorAll('p');

// По тегу
const divs = document.getElementsByTagName('div');

// По классу
const textElements = document.getElementsByClassName('text');

Изменение содержимого:

const el = document.getElementById('main');

// Изменить текст
el.textContent = 'Новый текст';

// Изменить HTML
el.innerHTML = '<span>HTML содержимое</span>';

// Создать новый элемент
const newDiv = document.createElement('div');
newDiv.textContent = 'Новый div';
el.appendChild(newDiv);

// Удалить элемент
el.removeChild(newDiv);
// или
newDiv.remove();

Работа с атрибутами:

const input = document.querySelector('input');

// Получить атрибут
const value = input.getAttribute('placeholder');

// Установить атрибут
input.setAttribute('placeholder', 'Введи текст');

// Проверить наличие
if (input.hasAttribute('disabled')) {
  input.removeAttribute('disabled');
}

// Использовать свойства
input.value = 'Новое значение';
input.disabled = true;

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

const btn = document.querySelector('button');

// Добавить класс
btn.classList.add('active');

// Удалить класс
btn.classList.remove('active');

// Переключить класс
btn.classList.toggle('active');

// Проверить наличие
if (btn.classList.contains('active')) {
  // ...
}

Навигация по дереву:

const el = document.querySelector('p');

// Родитель
const parent = el.parentElement;

// Дети
const children = el.children;
const firstChild = el.firstElementChild;
const lastChild = el.lastElementChild;

// Соседи
const next = el.nextElementSibling;
const prev = el.previousElementSibling;

События DOM

Основной механизм интерактивности:

const button = document.querySelector('button');

// Слушатель события
button.addEventListener('click', (event) => {
  console.log('Кнопка нажата');
  event.preventDefault(); // Отменить действие по умолчанию
});

// Другие события
document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM загружена');
});

window.addEventListener('resize', () => {
  console.log('Окно изменено');
});

const input = document.querySelector('input');
input.addEventListener('change', (e) => {
  console.log('Значение изменилось:', e.target.value);
});

input.addEventListener('keydown', (e) => {
  if (e.key === 'Enter') {
    console.log('Нажата Enter');
  }
});

Производительность DOM

Проблемы:

// ❌ Плохо: перерисовка после каждого добавления
const container = document.getElementById('container');
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = `Item ${i}`;
  container.appendChild(div); // Каждое добавление вызывает перерисовку!
}

// ✅ Хорошо: батчинг изменений
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = `Item ${i}`;
  fragment.appendChild(div);
}
container.appendChild(fragment); // Одна перерисовка

// ✅ Или innerHTML
const html = Array.from({ length: 1000 })
  .map((_, i) => `<div>Item ${i}</div>`)
  .join('');
container.innerHTML = html;

Оптимизация:

// Избегай частых обращений к DOM
const container = document.getElementById('main');
let height = 0;

// ❌ Плохо
for (let i = 0; i < 1000; i++) {
  height += document.getElementById('main').offsetHeight; // N+1 обращений!
}

// ✅ Хорошо
const mainHeight = container.offsetHeight;
for (let i = 0; i < 1000; i++) {
  height += mainHeight;
}

// Используй requestAnimationFrame для анимаций
function animate() {
  element.style.left = `${x}px`;
  requestAnimationFrame(animate);
}

DOM в современных фреймворках

В React, Vue, Angular DOM изменяется косвенно через фреймворк:

// React (JSX)
function MyComponent() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Увеличить
      </button>
    </div>
  );
}

// Vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="count++">Увеличить</button>
  </div>
</template>

Фреймворки автоматически обновляют DOM через Virtual DOM или реактивность.

Практический пример

// Простой список задач
class TodoApp {
  private todos: string[] = [];
  private todoList = document.getElementById('todo-list');
  private input = document.querySelector('input');
  private addBtn = document.querySelector('button');
  
  constructor() {
    this.addBtn.addEventListener('click', () => this.addTodo());
    this.input.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') this.addTodo();
    });
  }
  
  addTodo(): void {
    const text = this.input.value.trim();
    if (!text) return;
    
    this.todos.push(text);
    this.input.value = '';
    this.render();
  }
  
  render(): void {
    this.todoList.innerHTML = this.todos
      .map((todo, i) => `
        <li>
          ${todo}
          <button data-index="${i}">Удалить</button>
        </li>
      `)
      .join('');
    
    // Добавить обработчики для кнопок
    this.todoList.querySelectorAll('button').forEach(btn => {
      btn.addEventListener('click', (e) => {
        const index = parseInt(e.target.dataset.index);
        this.todos.splice(index, 1);
        this.render();
      });
    });
  }
}

new TodoApp();

Вывод

DOM — это критический API для фронтенда:

  • Выбор элементов — querySelector, getElementById
  • Изменение содержимого — textContent, innerHTML
  • Работа с событиями — addEventListener
  • Навигация по дереву — parentElement, children
  • Производительность — батчинг, fragment

Это основа интерактивности веб-приложений. В современных приложениях DOM обновляется фреймворками, но понимание его работы критично для оптимизации производительности.

Для чего используется DOM? | PrepBro