- Home »

Как изменять атрибуты, классы и стили в DOM
Если ты фулстек-разработчик или системный администратор, который в свободное время пилит веб-интерфейсы для мониторинга серверов, то работа с DOM — это твой хлеб насущный. Манипуляции с атрибутами, классами и стилями в JavaScript позволяют создавать динамичные дашборды, настраивать кастомные админки и делать интерфейсы, которые реагируют на состояние твоей инфраструктуры в реальном времени. Эта статья — твой практический гайд по всем основным способам изменения DOM-элементов, с примерами кода, которые можно сразу запустить на своём VPS или выделенном сервере.
Как это работает: основы манипуляций с DOM
DOM (Document Object Model) — это программный интерфейс для HTML-документов. Каждый элемент на странице — это объект со свойствами и методами. Когда ты меняешь атрибуты, классы или стили, браузер мгновенно перерисовывает страницу.
Основные способы доступа к элементам:
// Поиск элементов
const element = document.getElementById('server-status');
const elements = document.getElementsByClassName('warning');
const queryElement = document.querySelector('.cpu-usage');
const queryElements = document.querySelectorAll('div[data-server]');
Работа с атрибутами, классами и стилями осуществляется через различные API:
- Атрибуты: setAttribute(), getAttribute(), removeAttribute()
- Классы: className, classList (add, remove, toggle, contains)
- Стили: style.property, cssText, getComputedStyle()
Работа с атрибутами: пошаговое руководство
Атрибуты — это свойства HTML-элементов. Для админских интерфейсов часто используются data-атрибуты для хранения информации о серверах:
// Установка атрибутов
element.setAttribute('data-server-id', '12345');
element.setAttribute('title', 'CPU: 85%, RAM: 12GB');
// Получение атрибутов
const serverId = element.getAttribute('data-server-id');
const hasAttribute = element.hasAttribute('data-online');
// Удаление атрибутов
element.removeAttribute('data-temp');
// Работа с boolean атрибутами
element.disabled = true;
element.checked = false;
Практический пример для мониторинга серверов:
function updateServerStatus(serverId, isOnline) {
const serverElement = document.querySelector(`[data-server-id="${serverId}"]`);
if (isOnline) {
serverElement.setAttribute('data-status', 'online');
serverElement.setAttribute('title', 'Server is online');
} else {
serverElement.setAttribute('data-status', 'offline');
serverElement.setAttribute('title', 'Server is offline');
}
}
Манипуляции с классами: элегантно и эффективно
Классы — это основной способ стилизации элементов и индикации состояний. Современный подход — использовать classList API:
// Добавление классов
element.classList.add('active');
element.classList.add('server-online', 'high-load');
// Удаление классов
element.classList.remove('server-offline');
// Переключение классов
element.classList.toggle('collapsed');
// Проверка наличия класса
if (element.classList.contains('critical')) {
// Критическое состояние сервера
}
// Замена класса
element.classList.replace('warning', 'critical');
Сравнение старого и нового подходов:
Старый способ (className) | Новый способ (classList) | Преимущества |
---|---|---|
element.className += ‘ active’ | element.classList.add(‘active’) | Нет проблем с пробелами |
element.className = element.className.replace(‘active’, ”) | element.classList.remove(‘active’) | Простота и читаемость |
element.className.indexOf(‘active’) !== -1 | element.classList.contains(‘active’) | Булевый результат |
Пример системы индикации состояния серверов:
class ServerMonitor {
constructor() {
this.statusClasses = {
online: 'status-online',
offline: 'status-offline',
warning: 'status-warning',
critical: 'status-critical'
};
}
updateServerStatus(serverId, status) {
const element = document.querySelector(`#server-${serverId}`);
// Очищаем все статусы
Object.values(this.statusClasses).forEach(cls => {
element.classList.remove(cls);
});
// Добавляем новый статус
element.classList.add(this.statusClasses[status]);
// Добавляем анимацию при изменении
element.classList.add('status-changed');
setTimeout(() => element.classList.remove('status-changed'), 300);
}
}
Управление стилями: от простого к сложному
Стили можно изменять напрямую через JavaScript. Это мощный инструмент для создания динамичных интерфейсов:
// Изменение отдельных стилей
element.style.backgroundColor = '#ff0000';
element.style.fontSize = '16px';
element.style.display = 'none';
// Изменение нескольких стилей через cssText
element.style.cssText = 'color: red; font-size: 14px; margin: 10px;';
// Получение вычисленных стилей
const computedStyle = window.getComputedStyle(element);
const actualColor = computedStyle.color;
const actualMargin = computedStyle.marginTop;
Продвинутый пример с анимацией загрузки CPU:
function animateCPUUsage(element, targetPercent) {
const startPercent = parseInt(element.style.width) || 0;
const duration = 1000; // 1 секунда
const startTime = performance.now();
function animate(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentPercent = startPercent + (targetPercent - startPercent) * progress;
element.style.width = `${currentPercent}%`;
// Цвет зависит от загрузки
if (currentPercent < 50) {
element.style.backgroundColor = '#4CAF50'; // зеленый
} else if (currentPercent < 80) {
element.style.backgroundColor = '#FF9800'; // оранжевый
} else {
element.style.backgroundColor = '#F44336'; // красный
}
if (progress < 1) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
}
Положительные и отрицательные практики
✅ Хорошие практики:
- Используй classList вместо className для работы с классами
- Кеширuj DOM-элементы в переменных, если обращаешься к ним многократно
- Используй CSS-классы для сложных стилей вместо inline-стилей
- Группируй изменения DOM для минимизации reflow/repaint
❌ Антиpaттерны:
- Не делай многократные поиски одного элемента
- Избегай прямого изменения style для сложных стилей
- Не забывай про производительность при массовых операциях
Проблема | Плохо | Хорошо |
---|---|---|
Многократный поиск | document.querySelector('#el').style.color = 'red'; document.querySelector('#el').style.fontSize = '14px'; |
const el = document.querySelector('#el'); el.style.color = 'red'; el.style.fontSize = '14px'; |
Сложные стили | element.style.cssText = 'много стилей...'; | element.classList.add('prepared-class'); |
Автоматизация и скрипты для серверного мониторинга
Вот реальный пример скрипта для мониторинга серверов, который обновляет интерфейс в реальном времени:
class ServerDashboard {
constructor() {
this.wsConnection = null;
this.servers = new Map();
this.init();
}
init() {
this.connectWebSocket();
this.setupEventListeners();
}
connectWebSocket() {
this.wsConnection = new WebSocket('ws://localhost:8080/monitoring');
this.wsConnection.onmessage = (event) => {
const data = JSON.parse(event.data);
this.updateServerDisplay(data);
};
}
updateServerDisplay(serverData) {
const { serverId, cpu, memory, disk, status } = serverData;
const serverElement = document.querySelector(`#server-${serverId}`);
if (!serverElement) return;
// Обновляем прогресс-бары
this.updateProgressBar(serverElement.querySelector('.cpu-bar'), cpu);
this.updateProgressBar(serverElement.querySelector('.memory-bar'), memory);
this.updateProgressBar(serverElement.querySelector('.disk-bar'), disk);
// Обновляем статус
this.updateServerStatus(serverElement, status);
// Обновляем атрибуты для последующей обработки
serverElement.setAttribute('data-last-update', Date.now());
serverElement.setAttribute('data-cpu', cpu);
serverElement.setAttribute('data-memory', memory);
}
updateProgressBar(barElement, percentage) {
const progressFill = barElement.querySelector('.progress-fill');
// Анимированное изменение ширины
progressFill.style.transition = 'width 0.3s ease';
progressFill.style.width = `${percentage}%`;
// Изменение цвета в зависимости от значения
progressFill.classList.remove('low', 'medium', 'high', 'critical');
if (percentage < 50) {
progressFill.classList.add('low');
} else if (percentage < 75) {
progressFill.classList.add('medium');
} else if (percentage < 90) {
progressFill.classList.add('high');
} else {
progressFill.classList.add('critical');
}
// Обновляем текст
barElement.querySelector('.percentage-text').textContent = `${percentage}%`;
}
updateServerStatus(serverElement, status) {
const statusIndicator = serverElement.querySelector('.status-indicator');
// Очищаем предыдущие классы статуса
statusIndicator.classList.remove('online', 'offline', 'warning', 'maintenance');
// Добавляем новый статус
statusIndicator.classList.add(status);
// Обновляем атрибуты
statusIndicator.setAttribute('data-status', status);
statusIndicator.setAttribute('title', `Server is ${status}`);
// Добавляем пульсацию для критических состояний
if (status === 'offline' || status === 'critical') {
statusIndicator.classList.add('pulse');
} else {
statusIndicator.classList.remove('pulse');
}
}
}
// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', () => {
new ServerDashboard();
});
Альтернативные решения и библиотеки
Хотя нативный JavaScript мощен, существуют библиотеки, которые упрощают работу с DOM:
- jQuery — классика, но уже устарела для современных проектов
- Alpine.js — легковесная альтернатива для простых интерактивных элементов
- Stimulus — минималистичный фреймворк от создателей Ruby on Rails
- Lit — современная библиотека для создания веб-компонентов
Пример с Alpine.js для простого переключения состояний:
<div x-data="{ serverStatus: 'online' }">
<div :class="'server-' + serverStatus"
:data-status="serverStatus"
@click="serverStatus = serverStatus === 'online' ? 'offline' : 'online'">
Server Status: <span x-text="serverStatus"></span>
</div>
</div>
Производительность и оптимизация
При работе с большим количеством элементов важно учитывать производительность:
// Плохо: множественные reflow/repaint
for (let i = 0; i < 1000; i++) {
const element = document.getElementById(`server-${i}`);
element.style.display = 'block';
element.style.backgroundColor = 'red';
}
// Хорошо: пакетное обновление
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const element = document.getElementById(`server-${i}`);
element.style.cssText = 'display: block; background-color: red;';
}
// Еще лучше: используй requestAnimationFrame для больших операций
function batchUpdate(elements, callback) {
let index = 0;
const batchSize = 10;
function processBatch() {
const endIndex = Math.min(index + batchSize, elements.length);
for (let i = index; i < endIndex; i++) {
callback(elements[i], i);
}
index = endIndex;
if (index < elements.length) {
requestAnimationFrame(processBatch);
}
}
requestAnimationFrame(processBatch);
}
Интеграция с современными инструментами
Для продвинутых сценариев можно интегрировать DOM-манипуляции с другими инструментами:
- Web Components — создание переиспользуемых компонентов
- Intersection Observer — отслеживание видимости элементов
- Mutation Observer — отслеживание изменений DOM
- CSS Custom Properties — динамическое изменение CSS-переменных
Пример с CSS Custom Properties:
// Динамическое изменение цветовой темы
function setTheme(isDark) {
const root = document.documentElement;
if (isDark) {
root.style.setProperty('--primary-color', '#333');
root.style.setProperty('--background-color', '#1a1a1a');
root.style.setProperty('--text-color', '#fff');
} else {
root.style.setProperty('--primary-color', '#007bff');
root.style.setProperty('--background-color', '#fff');
root.style.setProperty('--text-color', '#333');
}
// Сохраняем настройку
localStorage.setItem('theme', isDark ? 'dark' : 'light');
}
Заключение и рекомендации
Работа с DOM в JavaScript — это фундаментальный навык для создания динамичных веб-интерфейсов. Для системных администраторов и разработчиков, работающих с серверной инфраструктурой, это особенно важно при создании дашбордов мониторинга, админских панелей и инструментов управления.
Ключевые выводы:
- Используй современные API: classList, setAttribute, querySelector
- Кеширuj DOM-элементы для повышения производительности
- Предпочитай CSS-классы inline-стилям для сложной стилизации
- Группируй изменения DOM для минимизации reflow/repaint
- Используй requestAnimationFrame для тяжелых операций
Когда использовать:
- Создание дашбордов мониторинга серверов
- Разработка админских интерфейсов
- Построение интерактивных форм конфигурации
- Реализация real-time обновлений статуса системы
Помни: хороший код — это не только работающий код, но и код, который легко поддерживать. Используй семантичные имена классов, комментируй сложную логику и всегда тестируй на разных устройствах и браузерах. Если планируешь деплоить свои решения, обязательно протестируй их на своём VPS или выделенном сервере в продакшен-окружении.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.