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

Как Shadow DOM связан с Virtual DOM?

2.2 Middle🔥 241 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Связь Shadow DOM и Virtual DOM

Это часто путают новички, но это совершенно разные концепции. Давайте разберёмся, что они собой представляют и почему они не связаны напрямую.

Virtual DOM (Виртуальный DOM)

Определение: Virtual DOM — это JavaScript представление реального DOM, которое существует в памяти приложения.

Как работает:

// React использует Virtual DOM
function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

// React сначала создаёт Virtual DOM
const vdom = {
  type: 'div',
  children: [
    {
      type: 'p',
      children: ['Count: 0']
    },
    {
      type: 'button',
      children: ['Increment']
    }
  ]
};

// Затем преобразует его в реальный DOM
const realDOM = document.createElement('div');
const p = document.createElement('p');
p.textContent = 'Count: 0';
realDOM.appendChild(p);
// ...

Процесс:

1. Изменение состояния
2. React пересчитывает Virtual DOM
3. React сравнивает старый и новый Virtual DOM (diffing)
4. React обновляет только изменённые элементы в реальном DOM (reconciliation)
5. Пользователь видит обновление

Зачем нужен Virtual DOM?

  • Производительность — вместо обновления всего DOM обновляют только изменённые части
  • Абстракция — разработчик пишет декларативный код, React управляет DOM
  • Batch updates — накапливает изменения и применяет их за раз

Shadow DOM (Теневой DOM)

Определение: Shadow DOM — это изолированное поддерево DOM, которое инкапсулировано от остального документа.

Как работает:

// Создаём Web Component с Shadow DOM
class MyCard extends HTMLElement {
  constructor() {
    super();
    // Создаём Shadow Root
    this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    // Пишем HTML в Shadow DOM
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          border: 1px solid #ccc;
          padding: 16px;
          border-radius: 8px;
        }
      </style>
      <div class="card">
        <h2>Card Title</h2>
        <p><slot></slot></p>
      </div>
    `;
  }
}

customElements.define('my-card', MyCard);
<!-- Использование -->
<my-card>
  <p>This is card content</p>
</my-card>

<!-- Shadow DOM инкапсулирован, не видно в DevTools по умолчанию -->

Структура:

Обычный DOM:              Shadow DOM:
┌─────────────────┐      ┌──────────────────────┐
│ <my-card>       │      │ #shadow-root         │
│  <p>Content</p> │      │   <style>            │
│ </my-card>      │      │   .card { ... }      │
│                 │      │   </style>           │
│ (видно всем)    │      │   <div class="card"  │
└─────────────────┘      │     <h2>...</h2>     │
                         │   </div>             │
                         │ (инкапсулировано)    │
                         └──────────────────────┘

Зачем нужен Shadow DOM?

  • Инкапсуляция — стили внутри Shadow DOM не влияют на остальную страницу
  • Реиспользование компонентов — создаём переиспользуемые Web Components
  • Изоляция логики — JavaScript внутри изолирован от глобального контекста

Ключевые различия

ПараметрVirtual DOMShadow DOM
Что этоJavaScript объектИзолированное DOM поддерево
Где существуетВ памяти приложенияВ браузере (в DOM)
НазначениеОптимизация обновленийИнкапсуляция компонентов
ИспользуютReact, Vue, AngularWeb Components, браузер
ВидимостьНевидим в DevToolsВидна в DevTools (если включено)
Влияние на стилиВиртуальный, не влияетИзолирует стили от внешних
ИнкапсуляцияЛогическая (в коде)Физическая (в браузере)

Практический пример: разница

// Virtual DOM — React
function MyButton() {
  const [clicked, setClicked] = useState(false);

  return (
    <button
      style={{
        background: clicked ? 'green' : 'blue',
        color: 'white'
      }}
      onClick={() => setClicked(!clicked)}
    >
      {clicked ? 'Clicked!' : 'Click me'}
    </button>
  );
}

// Shadow DOM — Web Component
class MyButton extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.clicked = false;
  }

  connectedCallback() {
    this.render();
    this.addEventListener('click', () => this.toggle());
  }

  toggle() {
    this.clicked = !this.clicked;
    this.render();
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>
        button {
          background: ${this.clicked ? 'green' : 'blue'};
          color: white;
        }
      </style>
      <button>${this.clicked ? 'Clicked!' : 'Click me'}</button>
    `;
  }
}

customElements.define('my-button', MyButton);

Можно ли использовать вместе?

Да! React + Shadow DOM + Web Components:

// Web Component с Shadow DOM
class MyCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>.card { border: 1px solid #ccc; }</style>
      <div class="card"><slot></slot></div>
    `;
  }
}

customElements.define('my-card', MyCard);

// React компонент использует Web Component
function App() {
  const [items, setItems] = useState([1, 2, 3]);

  return (
    <div>
      {items.map((item) => (
        <my-card key={item}>
          <p>Item {item}</p>
        </my-card>
      ))}
    </div>
  );
}

// React управляет Virtual DOM
// Web Component изолирует Shadow DOM

Реальные примеры

Virtual DOM используют:

  • React
  • Vue
  • Angular (имеет свой механизм)
  • Svelte (компилирует Virtual DOM)

Shadow DOM используют:

  • Google Material Design Components
  • Polymer (Google)
  • Lit (Google)
  • Shoelace (компоненты для веб)
  • Встроенные браузерные элементы (video, input type="date")
<!-- Посмотри в DevTools видео элемента -->
<video controls>
  <source src="movie.mp4" type="video/mp4">
</video>
<!-- У него есть скрытый Shadow DOM! -->

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

Virtual DOM:

  • Более эффективен для частых обновлений большого приложения
  • Хорош для SPA

Shadow DOM:

  • Хорош для переиспользуемых компонентов
  • Изоляция может быть более производительной для отдельных компонентов

Заключение

Virtual DOM и Shadow DOM — это совершенно разные концепции:

  • Virtual DOM — техника оптимизации обновлений DOM в памяти
  • Shadow DOM — браузерный API для инкапсуляции и изоляции

Они не конкурируют, а дополняют друг друга. Ты можешь использовать Web Components с Shadow DOM внутри React приложения с Virtual DOM. Это даёт лучшее из обоих миров: оптимизированные обновления React и инкапсулированные компоненты Web Components.

Как Shadow DOM связан с Virtual DOM? | PrepBro