← Назад к вопросам
Есть ли Shadow DOM в React?
2.0 Middle🔥 141 комментариев
#Браузер и сетевые технологии
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Есть ли Shadow DOM в React?
React и Shadow DOM — это две разные технологии на разных уровнях абстракции. React работает с Virtual DOM, а Shadow DOM — это стандарт Web Components. Расскажу про их взаимодействие.
Что такое Shadow DOM?
Shadow DOM (Теневой DOM) — это стандарт Web Components, который позволяет создавать инкапсулированное дерево элементов, изолированное от основного DOM.
// Создание Shadow DOM
const hostElement = document.getElementById('host');
const shadowRoot = hostElement.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<style>
/* Стили изолированы внутри Shadow DOM */
p { color: red; }
</style>
<p>Это текст в Shadow DOM</p>
`;
Разница между Virtual DOM (React) и Shadow DOM
| Аспект | Virtual DOM (React) | Shadow DOM |
|---|---|---|
| Что это? | Копия реального DOM в памяти | Инкапсулированное дерево элементов |
| Цель | Оптимизация обновлений | Инкапсуляция стилей и структуры |
| Видно в DevTools? | Нет (только JavaScript объект) | Да (отдельное дерево) |
| Изоляция стилей | Нет (нужно использовать BEM, CSS-in-JS) | Да (встроенная) |
| Стандарт браузера | Реализовано в React | Да, стандарт W3C |
| Совместимость | Работает везде | Не поддерживается IE11 |
React и Shadow DOM
React НЕ использует Shadow DOM по умолчанию, но можно создавать Web Components с Shadow DOM и использовать их в React.
Создание Web Component с Shadow DOM
// Классический Web Component с Shadow DOM
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
:host {
display: block;
padding: 10px;
border: 1px solid #ccc;
}
p {
color: blue;
margin: 0;
}
</style>
<p>Компонент с Shadow DOM</p>
`;
}
}
customElements.define('my-component', MyComponent);
<!-- Использование в HTML -->
<my-component></my-component>
Использование Web Component в React
// React компонент, использующий Web Component с Shadow DOM
function App() {
return (
<div>
{/* Web Component работает в React как обычный HTML элемент */}
<my-component></my-component>
</div>
);
}
Передача свойств и атрибутов
// Web Component (с Shadow DOM)
class MyButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
button {
background: ${this.getAttribute('color') || 'blue'};
color: white;
padding: 10px 20px;
}
</style>
<button><slot></slot></button>
`;
}
}
customElements.define('my-button', MyButton);
// Использование в React
function App() {
return (
<>
{/* Атрибуты передаются как на обычный HTML элемент */}
<my-button color="red">Нажми</my-button>
<my-button color="green">Нажми</my-button>
</>
);
}
Слоты (Slots) в Shadow DOM
Slot — это плейсхолдер в Shadow DOM для вставки содержимого.
class Card extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
.card {
border: 1px solid #ddd;
padding: 20px;
border-radius: 8px;
}
</style>
<div class="card">
<h2><slot name="title"></slot></h2>
<p><slot name="content"></slot></p>
<footer><slot name="footer"></slot></footer>
</div>
`;
}
}
customElements.define('my-card', Card);
// Использование со слотами
function App() {
return (
<my-card>
<h3 slot="title">Заголовок</h3>
<p slot="content">Основной контент</p>
<span slot="footer">Подвал</span>
</my-card>
);
}
Можно ли сделать Shadow DOM в React компонентах?
// Да, можно создать React компонент с Shadow DOM
import { useEffect, useRef } from 'react';
function MyReactComponent() {
const divRef = useRef(null);
useEffect(() => {
if (divRef.current && !divRef.current.shadowRoot) {
const shadow = divRef.current.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
p { color: red; }
</style>
<p>Текст в Shadow DOM</p>
`;
}
}, []);
return <div ref={divRef}></div>;
}
Проблемы React с Shadow DOM
1. React не может управлять содержимым Shadow DOM
function App() {
const [text, setText] = useState('Привет');
const divRef = useRef(null);
useEffect(() => {
const shadow = divRef.current.attachShadow({ mode: 'open' });
shadow.innerHTML = `<p>${text}</p>`; // React НЕ обновляет это!
}, [text]); // Зависимость text не помогает
return (
<>
<div ref={divRef}></div>
<button onClick={() => setText('Пока')}>Изменить</button>
</>
);
}
2. Портали (Portals) работают лучше
import { createPortal } from 'react-dom';
function App() {
const [text, setText] = useState('Привет');
const divRef = useRef(null);
useEffect(() => {
divRef.current.attachShadow({ mode: 'open' });
}, []);
return (
<>
<div ref={divRef}>
{/* React может управлять этим содержимым через портал */}
{createPortal(
<p style={{ color: 'red' }}>{text}</p>,
divRef.current.shadowRoot
)}
</div>
<button onClick={() => setText('Пока')}>Изменить</button>
</>
);
}
Когда использовать Shadow DOM?
Плюсы:
- Инкапсуляция стилей (CSS не влияет друг на друга)
- Скрытие сложной реализации
- Web Components переиспользуются везде
Минусы:
- Сложность с React
- Проблемы с контролем содержимого
- Пересекающиеся стили сложнее дебагить
Практический пример: Web Component с Shadow DOM в React
// components/Modal.js
class Modal extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<style>
:host {
--modal-bg: white;
}
.modal {
background: var(--modal-bg);
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
</style>
<div class="modal">
<slot></slot>
</div>
`;
}
}
customElements.define('custom-modal', Modal);
// App.jsx
function App() {
return (
<custom-modal>
<h2>Заголовок модали</h2>
<p>Содержимое модали</p>
</custom-modal>
);
}
Ключевые моменты
- React использует Virtual DOM, НЕ Shadow DOM
- Shadow DOM — это стандарт для Web Components (инкапсуляция)
- Можно создавать Web Components с Shadow DOM и использовать в React
- React не может управлять содержимым Shadow DOM напрямую
- Для хорошей интеграции с React нужны Portals и useRef
- Shadow DOM полезен для переиспользуемых компонентов с изолированными стилями