Шаблонизация через HTMLElement опирается на прямое
использование DOM API без промежуточных DSL и без внешних
шаблонизаторов. В контексте современных сборщиков, таких как Parcel,
этот подход становится особенно устойчивым благодаря предсказуемой
работе модулей, быстрой пересборке и минимальному количеству абстракций
поверх браузерного API.
Основная идея заключается в том, что UI строится не как строка HTML,
а как дерево объектов Node, создаваемое программно. Это
исключает этап парсинга HTML-строк и позволяет работать с интерфейсом
как с обычной структурой данных.
DOM-элемент создаётся через document.createElement,
после чего его свойства и дочерние узлы настраиваются императивно:
const button = document.createElement('button');
button.textContent = 'Сохранить';
button.className = 'primary-button';
document.body.appendChild(button);
Такой подход формирует основу шаблонизации: каждый UI-фрагмент
представляется функцией, возвращающей готовый
HTMLElement.
Повторно используемые элементы удобно оформлять как функции-фабрики:
function createButton(label) {
const button = document.createElement('button');
button.textContent = label;
button.className = 'button';
return button;
}
const saveButton = createButton('Сохранить');
const cancelButton = createButton('Отмена');
document.body.append(saveButton, cancelButton);
Такой уровень абстракции уже формирует шаблон, где структура UI отделена от места использования.
Шаблонизация через HTMLElement становится масштабируемой
при композиции:
function createCard(title, content) {
const wrapper = document.createElement('div');
wrapper.className = 'card';
const header = document.createElement('h3');
header.textContent = title;
const body = document.createElement('p');
body.textContent = content;
wrapper.append(header, body);
return wrapper;
}
document.body.appendChild(
createCard('Заголовок', 'Содержимое блока')
);
Композиционный подход заменяет необходимость строковых шаблонов и позволяет избегать проблем с экранированием HTML.
В рамках Parcel каждый компонент, реализованный через
HTMLElement, обычно оформляется как отдельный
ES-модуль:
// button.js
export function createButton(label) {
const button = document.createElement('button');
button.textContent = label;
return button;
}
// main.js
import { createButton } from './button.js';
document.body.appendChild(createButton('OK'));
Parcel автоматически отслеживает зависимости между модулями и перестраивает только изменённые части, что делает подход с DOM-шаблонами особенно эффективным в разработке UI.
Хотя основа шаблонизации — DOM API, template literals могут использоваться как вспомогательный инструмент для генерации текстовых узлов:
function createUser(name, age) {
const container = document.createElement('div');
container.innerHTML = `
<span class="name">${name}</span>
<span class="age">${age}</span>
`;
return container;
}
Однако такой подход снижает контроль над структурой DOM и требует осторожного обращения с динамическими данными.
Альтернативой является полное исключение innerHTML:
function createUser(name, age) {
const container = document.createElement('div');
const nameEl = document.createElement('span');
nameEl.textContent = name;
const ageEl = document.createElement('span');
ageEl.textContent = String(age);
container.append(nameEl, ageEl);
return container;
}
Шаблонизация на HTMLElement часто реализует модель
«перерисовки через пересоздание»:
function renderCounter(value) {
const root = document.createElement('div');
const label = document.createElement('span');
label.textContent = `Значение: ${value}`;
root.append(label);
return root;
}
let state = 0;
function update() {
const newView = renderCounter(state);
app.replaceChildren(newView);
}
Здесь состояние не привязано к DOM напрямую, а DOM строится заново при изменении данных.
Более оптимизированный вариант предполагает обновление только изменённых узлов:
const label = document.createElement('span');
label.textContent = '0';
document.body.appendChild(label);
function increment() {
state++;
label.textContent = String(state);
}
Такой подход уменьшает количество операций пересборки DOM и повышает производительность.
Стили могут применяться напрямую через свойства элемента:
const box = document.createElement('div');
box.style.width = '100px';
box.style.height = '100px';
box.style.backgroundColor = 'tomato';
Либо через классы:
box.classList.add('box', 'box--active');
Parcel при этом позволяет импортировать CSS прямо в JavaScript-модули:
import './styles.css';
Это обеспечивает автоматическую сборку стилей вместе с DOM-структурой.
Шаблонизация через HTMLElement естественно приводит к
компонентной архитектуре:
export function createModal(title, content) {
const overlay = document.createElement('div');
overlay.className = 'overlay';
const modal = document.createElement('div');
modal.className = 'modal';
const header = document.createElement('h2');
header.textContent = title;
const body = document.createElement('div');
body.textContent = content;
modal.append(header, body);
overlay.append(modal);
return overlay;
}
Компонент становится чистой функцией, возвращающей DOM-структуру без скрытых зависимостей.
События привязываются напрямую к элементам:
function createCounter() {
const button = document.createElement('button');
const label = document.createElement('span');
let value = 0;
button.textContent = 'Увеличить';
label.textContent = String(value);
button.addEventListener('click', () => {
value++;
label.textContent = String(value);
});
const wrapper = document.createElement('div');
wrapper.append(button, label);
return wrapper;
}
Такой стиль исключает необходимость декларативных обработчиков и сохраняет полный контроль над поведением.
При использовании HTMLElement-шаблонов важно учитывать
стоимость операций:
Оптимизация достигается через:
Шаблонизация через HTMLElement формирует модель, в
которой:
В связке с Parcel такой подход становится предсказуемым инструментом построения интерфейсов без дополнительного слоя абстракции над DOM.