DevGang
Авторизоваться

Основы внутреннего устройства React

React - одна из самых популярных библиотек javascript для создания пользовательских интерфейсов. Основное преимущество React заключается в том, что при обновлении обновляются только те элементы DOM, которые необходимо обновить. Это достигается с помощью виртуальной модели DOM, которая является не чем иным, как внутренним представлением нашего пользовательского интерфейса.

Давайте попробуем понять, как React управляет виртуальным домом и как он развивает структуру виртуального дома для поддержки параллельной версии.

Начнем с основ.

JSX

React представляет JSX для удобства разработчиков. JSX - это синтаксический сахар для React.createElement(type, props, ... children) или _jsx / jsxs

Например, когда мы определяем такой компонент

const profile = (
	<div>
		<img src="avatar.png" className="profile"/>
		<h3>{[user.firstName, user.lastName].join(" ")}</h3>
	</div>
);

компилятор babel переносит приведенный выше код в

const profile = React.createElement(
	"div",
	null,
	React.createElement("img", { src: "avatar.png", className: "profile" }),
	React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
);

React.createElement возвращает объект JS, описывающий узел и его свойства.
Например:

const profile = <h1 className='welcome'>Hello World </h1>

вернет что-то вроде этого

{
  type: 'h1',
  props: {
     className: 'welcome',
     children: ['Hello World']
  },
  ref: null,
  key: null,
  $$typeof: Symbol(react.element)
}

Возвращенный элемент имеет следующие свойства.

type
Тип элемента.
Если это настраиваемый элемент React, типом будет ссылка на функцию / класс элемента.

Если это элемент хоста (например, div в DOM), тип будет строковым.

  1. props
    Свойства элемента, такие как его дочерние элементы, цвет и т. д.,
  2. $$typeof
    Этот ключ нужен только для того, чтобы компонент был создан для предотвращения XSS.
  3. key
    Он используется для однозначной идентификации элемента в случае, если тип элемента недостаточен для его уникальной идентификации.
  4. ref
    Ссылка на экземпляр, если это настраиваемый элемент React, или ссылка на узел dom, если это элемент хоста

Использование этого объекта создает древовидную структуру данных, то есть виртуальную модель DOM, и сохраняет ее в памяти.

Согласие

Когда происходит обновление, React использует ранее созданный виртуальный дом и генерирует новое дерево на основе обновления. React сравнивает эти две версии и эффективно обновляет элементы в DOM. Этот процесс называется согласованием.

Но если React действительно сравнивает каждый узел / объект в дереве с его предыдущей версией, это займет много времени, верно? Чтобы избежать такой реакции, используется эвристический алгоритм, основанный на следующих правилах.

Элементы разных типов будут генерировать разные ветви и поддеревья

Например:

<div> Hi I am a div </div>

Если указанный выше элемент изменится на следующий элемент

<span> Hi I am a span </span>

Затем response удалит div и добавит span в его родительский элемент. Аналогично, если

<Hello/>

/* Changes to */

<Bye/>

Затем response отключит элемент Hello или его экземпляр и смонтирует Bye

Элементы одного типа

Если тип обоих элементов одинаковый, он проверит, изменились ли свойства. Если они будут изменены, react изменит свойства элемента.

Например:

<Message text='Hi'/> ==> <Message text='Bye'/>

изменит свойство текста с «Hi» на «Bye» в экземпляре сообщения.

<div className='active'/> ==> <div className='inactive'/>

изменит класс элемента div

Элементы одного типа, но с разными свойствами

Допустим, мы хотим перечислить несколько фруктов вроде следующего

<ul>
  <li>Banana 🍌</li>
  <li>Cherry 🍒</li>
</ul>

И из-за обновления мы добавляем запись к первому дочернему элементу ul, теперь наш компонент будет выглядеть так.

<ul>
  <li>Apple 🍎 </li>
  <li>Banana 🍌</li>
  <li>Cherry 🍒</li>
</ul>

Поскольку react работает по нашим вышеупомянутым правилам, react будет выполнять следующие действия.

  1. Сначала проверяет тип элемента ul. Поскольку он одинаков в обеих версиях, он приступает к проверке его свойств. Поскольку дочерние элементы изменены (ссылка будет изменена), он начинает проверять каждый элемент li
  2. Проверяет первый элемент элемента ul, т.е. li в обеих версиях, поскольку текстовое содержимое изменено с Banana 🍌 на Apple 🍎 , он обновляет изменения в DOM. Затем он переходит к проверке следующего элемента
  3. Теперь он проверяет второй элемент li и обновляет изменение текста в DOM с Cherry🍒  на Banana🍌.
  4. Затем он обнаруживает, что внизу создан новый элемент. Таким образом, он создает новый элемент li и добавляет его к элементу ul.

Вы заметили что-нибудь необычное в этом поведении? Apple - это тот, который был добавлен к первому, но React без необходимости обновляет два других элемента, верно? т.е. вместо выполнения одного обновления, response выполняет три обновления.

Чтобы избежать такой реакции, введен ключ для однозначной идентификации каждого элемента.

Элементы одного типа, но с разными ключами теперь будут однозначно идентифицироваться и обновляться. Итак, если мы представим ключ к приведенному выше примеру

<ul>
  <li key={1}>Banana 🍌</li>
  <li key={2}>Cherry 🍒</li>
</ul>

к

<ul>
  <li key={0}>Apple 🍎 </li>
  <li key={1}>Banana 🍌</li>
  <li key={2}>Cherry 🍒</li>
</ul>

Теперь React, сравнивая первый элемент, который знает, что Apple newly недавно добавлен в список, и выполняет это единственное обновление.

Обратите внимание, что использование индекса в качестве ключа может создать некоторые проблемы, особенно когда каждый из ваших компонентов имеет внутреннее состояние и переупорядочивание между списками довольно распространено.

#React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

В подарок 100$ на счет при регистрации

Получить