Веб-компоненти - вбудований у браузер спосіб створювати власні HTML-елементи. Три частини:
1. Користувацькі елементи (custom elements) - власний тег з поведінкою:
class CopyButton extends HTMLElement {
connectedCallback() {
this.addEventListener('click', () => {
navigator.clipboard.writeText(this.getAttribute('text'));
});
}
}
customElements.define('copy-button', CopyButton);
<copy-button text="composer require laravel/sanctum">Копіювати</copy-button>
Назва обов'язково містить дефіс - щоб не зіткнутися з майбутніми стандартними тегами. Колбеки життєвого циклу: connectedCallback, disconnectedCallback, attributeChangedCallback (для атрибутів зі списку observedAttributes).
2. Shadow DOM - ізольоване піддерево всередині елемента:
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>button { color: red; }</style>
<button><slot></slot></button>
`;
- стилі сторінки не проникають усередину, а стилі компонента не витікають назовні - справжня ізоляція CSS;
document.querySelectorне знаходить елементи всередині тіньового дерева;- налаштування ззовні - через CSS-змінні (вони успадковуються крізь межу) і
::part().
3. <template> і <slot> - розмітка-заготовка й місця, куди потрапляє вміст, переданий компоненту.
Коли веб-компоненти доречні:
- елементи, що мають працювати будь-де: у Blade, Vue, React, на статичній сторінці. Дизайн-системи великих компаній і віджети для вбудовування на чужі сайти;
- ізоляція стилів від CSS сторінки, яку ви не контролюєте;
- «острівці» інтерактивності на серверно-рендерених сторінках без фреймворку;
- довговічність: стандарт браузера не застаріває так, як версії фреймворків.
Обмеження:
- немає реактивності й шаблонізації з коробки: оновлення DOM при зміні даних - вручну (або бібліотека на кшталт Lit);
- серверний рендеринг Shadow DOM можливий через декларативний
<template shadowrootmode="open">, але екосистема тут слабша, ніж у фреймворків; - форми: елементи всередині Shadow DOM не беруть участі у відправці форми без
ElementInternals; - доступність: зв'язки
aria-labelledbyіforне працюють крізь межу тіньового дерева; - Tailwind не стилізує вміст Shadow DOM - глобальні класи туди не потрапляють.
З фреймворками: Vue вміє компілювати компоненти у веб-компоненти (defineCustomElement), React 19 повноцінно підтримує їх як елементи. Alpine і Livewire працюють з користувацькими елементами як із звичайними тегами (без Shadow DOM).