0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В одном из предыдущих курсов впервые рассматривалось изменение DOM в процессе взаимодействия со страницей. Этот способ резко отличается от того, который использовался в курсе<a>JS: DOM API</a>. Важнейшее отличие связано с тем, как происходит изменение состояния отрисованного экрана. При прямом манипулировании DOM нужно сделать следующее:</p>
1
<p>В одном из предыдущих курсов впервые рассматривалось изменение DOM в процессе взаимодействия со страницей. Этот способ резко отличается от того, который использовался в курсе<a>JS: DOM API</a>. Важнейшее отличие связано с тем, как происходит изменение состояния отрисованного экрана. При прямом манипулировании DOM нужно сделать следующее:</p>
2
<ol><li>Удалить из DOM то, что стало неактуально для следующего состояния.</li>
2
<ol><li>Удалить из DOM то, что стало неактуально для следующего состояния.</li>
3
<li>Изменить, если надо, те элементы, которые присутствуют на экране и должны остаться.</li>
3
<li>Изменить, если надо, те элементы, которые присутствуют на экране и должны остаться.</li>
4
<li>Добавить новые элементы на страницу (точечно).</li>
4
<li>Добавить новые элементы на страницу (точечно).</li>
5
</ol><p>Другими словами, чтобы перейти в новое состояние, нужно изменить старое. Значит про него надо знать.</p>
5
</ol><p>Другими словами, чтобы перейти в новое состояние, нужно изменить старое. Значит про него надо знать.</p>
6
<p>В React всё совсем по-другому. После любого изменения и вызова setState React создаёт новое состояние и отрисовывает все компоненты так, как будто это происходит с нуля. На самом деле отрисовка действительно происходит с нуля. Неважно, что было до этого момента на экране и как оно располагалось. Любое изменение в React приводит к тому, что приложение отрисовывается заново.</p>
6
<p>В React всё совсем по-другому. После любого изменения и вызова setState React создаёт новое состояние и отрисовывает все компоненты так, как будто это происходит с нуля. На самом деле отрисовка действительно происходит с нуля. Неважно, что было до этого момента на экране и как оно располагалось. Любое изменение в React приводит к тому, что приложение отрисовывается заново.</p>
7
<p>Создатели React называют этот подход<em>one-way data flow</em>:</p>
7
<p>Создатели React называют этот подход<em>one-way data flow</em>:</p>
8
<ol><li>Действия пользователя приводят к изменению состояния приложения (через setState).</li>
8
<ol><li>Действия пользователя приводят к изменению состояния приложения (через setState).</li>
9
<li>React запускает цикл отрисовки. Начиная от того компонента, в котором было изменено состояние (как правило, корневой компонент), через пропсы данные постепенно распространяются от компонентов более высокого уровня до самых глубинных компонентов.</li>
9
<li>React запускает цикл отрисовки. Начиная от того компонента, в котором было изменено состояние (как правило, корневой компонент), через пропсы данные постепенно распространяются от компонентов более высокого уровня до самых глубинных компонентов.</li>
10
<li>Получившийся html интегрируется в страницу.</li>
10
<li>Получившийся html интегрируется в страницу.</li>
11
</ol><p>Те, кто хорошо знаком с функциональным подходом, могут увидеть прямую связь. React действительно делает мир неизменяемым (immutable). Самый простой способ реализовать подобное поведение - использовать mountElement.innerHTML, который заменяет html целиком после вызова setState. Хотя на практике этот подход сопряжён с кучей сложностей (пример реализации смотрите в дополнительных материалах), он позволяет в 200 строк построить библиотеку, которая будет работать как React.</p>
11
</ol><p>Те, кто хорошо знаком с функциональным подходом, могут увидеть прямую связь. React действительно делает мир неизменяемым (immutable). Самый простой способ реализовать подобное поведение - использовать mountElement.innerHTML, который заменяет html целиком после вызова setState. Хотя на практике этот подход сопряжён с кучей сложностей (пример реализации смотрите в дополнительных материалах), он позволяет в 200 строк построить библиотеку, которая будет работать как React.</p>
12
<p>Главная проблема при использовании innerHTML связана с производительностью. Сказать, что это медленно - ничего не сказать. Поэтому создатели React пошли другим путём.</p>
12
<p>Главная проблема при использовании innerHTML связана с производительностью. Сказать, что это медленно - ничего не сказать. Поэтому создатели React пошли другим путём.</p>
13
<h2>Дерево виртуального DOM</h2>
13
<h2>Дерево виртуального DOM</h2>
14
<p>Ранее в курсе говорилось, что компоненты отрисовываются, и это немного не так. В реальности после того, как отработает их рендеринг (вызов функции render для всего дерева компонентов), создаётся так называемый<em>виртуальный DOM</em>(virtual DOM). Это просто JS-объект определённой структуры, который отражает состояние экрана. Далее React сравнивает новое дерево виртуального DOM со старым и строит разницу между ними ("дифф", или объект, описывающий разницу между старым и новым состоянием). И только в этот момент начинается отрисовка нового состояния в реальный DOM. Здесь уже должно быть понятно, что React умнее, чем кажется на первый взгляд, и вносит изменения в реальный DOM настолько эффективно, насколько это возможно, ведь он знает КАК его надо изменить.</p>
14
<p>Ранее в курсе говорилось, что компоненты отрисовываются, и это немного не так. В реальности после того, как отработает их рендеринг (вызов функции render для всего дерева компонентов), создаётся так называемый<em>виртуальный DOM</em>(virtual DOM). Это просто JS-объект определённой структуры, который отражает состояние экрана. Далее React сравнивает новое дерево виртуального DOM со старым и строит разницу между ними ("дифф", или объект, описывающий разницу между старым и новым состоянием). И только в этот момент начинается отрисовка нового состояния в реальный DOM. Здесь уже должно быть понятно, что React умнее, чем кажется на первый взгляд, и вносит изменения в реальный DOM настолько эффективно, насколько это возможно, ведь он знает КАК его надо изменить.</p>
15
<p>Из описанного выше есть важное следствие. Тот реальный DOM, который находится под контролем React (это все потомки элемента, в который рендерится корневой компонент), не может изменяться никем снаружи React-приложения. Если подобное произойдёт, то React не сможет нормально функционировать, ведь ему приходится отслеживать текущее состояние DOM для того, чтобы производить вычисления "диффа". Когда подобное происходит, React ругается и говорит, что ему мешают работать.</p>
15
<p>Из описанного выше есть важное следствие. Тот реальный DOM, который находится под контролем React (это все потомки элемента, в который рендерится корневой компонент), не может изменяться никем снаружи React-приложения. Если подобное произойдёт, то React не сможет нормально функционировать, ведь ему приходится отслеживать текущее состояние DOM для того, чтобы производить вычисления "диффа". Когда подобное происходит, React ругается и говорит, что ему мешают работать.</p>
16
<p>Важно: виртуальный DOM - не самоцель React, как многие думают. Это просто эффективный способ реализовать идею<em>one-way data flow</em>. Если бы работал вариант с innerHTML, то никто бы не делал виртуальный DOM.</p>
16
<p>Важно: виртуальный DOM - не самоцель React, как многие думают. Это просто эффективный способ реализовать идею<em>one-way data flow</em>. Если бы работал вариант с innerHTML, то никто бы не делал виртуальный DOM.</p>
17
<p>И хотя построение JS-объекта - это гораздо более дешёвая операция, чем работа с реальным DOM, все равно могут возникать ситуации, когда процесс вычисления занимает много времени, и это тормозит приложение. Этой теме посвящён один из следующих уроков.</p>
17
<p>И хотя построение JS-объекта - это гораздо более дешёвая операция, чем работа с реальным DOM, все равно могут возникать ситуации, когда процесс вычисления занимает много времени, и это тормозит приложение. Этой теме посвящён один из следующих уроков.</p>