Skip to content

Virtual DOM

Sᴛѧʀʟɪɴɢ edited this page Oct 30, 2018 · 7 revisions

Как написать свой Virtual DOM

Основные концепции

  • Virtual DOM это любой вид представления реального DOM (any kind of representation of a real DOM).
  • Когда мы что-то изменяем в нашем виртуальном DOM-дереве, мы получаем новое виртуальное дерево. Алгоритм сравнивает старое и новое деревья, находит их различия и делает лишь необходимые изменения в реальном DOM. Что и отражает слово virtual.

Представление нашего дерева DOM

Итак, для начала нам нужно как-то хранить исходное дерево DOM в памяти. Для примера:

<ul class=”list”>  
  <li>item 1</li>    
  <li>item 2</li>    
</ul>

Для этого подойдут обычные JS-объекты:

{  
 type: ‘ul’,
 props: { ‘class’: ‘list’ },
 children: [
  { type: ‘li’, props: {}, children: [‘item 1] },
  { type: ‘li’, props: {}, children: [‘item 2] }
 ]
}

Здесь мы представляем DOM узлы-элементы как объекты. Будем представлять текстовые DOM-узлы как обычные JS-строки.

Для рассмотрения общего случая нам понадобится вспомогательная функция (helper):

const h = (type, props, ...children) => ({ type, props, children });

С её помощью мы можем переписать код так:

h(
 'ul',
 { 'class' : 'list' },
 h('li', {}, 'item 1'),
 h('li', {}, 'item 2'),
);

Уже лучше, но можно пойти дальше. Как работает JSX? Babel транслирует код (transpile) во что-то такое:

React.createElement(
 ‘ul’,
 { className: ‘list’ },
 React.createElement(‘li’, {}, ‘item 1),
 React.createElement(‘li’, {}, ‘item 2),
);

Что очень похоже на нашу вспомогательную функцию. Чтобы сделать что-то подобное, мы можем использовать jsx pragma. Для этого нужно просто над исходным HTML кодом оставить комментарий вида:

/* @jsx h */

В этом случае мы укажем Babel'ю, что нужно транслировать этот JSX, но вместо React.createElement() использовать нашу вспомогательную функцию h().

Таким образом код

/* @jsx h */
const d = (<div>Hello</div>);

транслируется Babel'ем в код:

const d = h('div', {});

А после выполнения вспомогательной функции получим простые JS объекты - наше представление Virtual DOM:

const d = ({ type: 'div', props: {}, children: [] });

Применение нашего представления DOM

У нас уже есть представление дерева DOM со своей структурой в виде объектов. Теперь нам нужно создать реальный DOM по этой структуре.

Clone this wiki locally