Рендеринг и фиксация в React
год назад·1 мин. на чтение
Прежде чем ваши компоненты отобразятся на экране, они должны быть обработаны React. Понимание шагов этого процесса поможет вам понять, как выполняется ваш код, и объяснить его поведение.
Содержание туториала по React
Прежде чем ваши компоненты отобразятся на экране, они должны быть обработаны React. Понимание шагов этого процесса поможет вам понять, как выполняется ваш код, и объяснить его поведение.
Представьте, что ваши компоненты — повара на кухне, собирающие вкусные блюда из ингредиентов. В этом сценарии React — это официант, который принимает запросы от клиентов и приносит им их заказы. Этот процесс запроса и обслуживания пользовательского интерфейса состоит из трех этапов:
- Запуск рендера (доставка заказа гостя на кухню)
- Рендер компонента (подготовка заказа на кухне)
- Фиксация (commit) в DOM (размещение заказа на столе)
Шаг 1. Запуск рендеринга
Есть две причины для рендеринга компонента:- Это начальный рендер компонента.
- Состояние компонента (или одного из его предков) было обновлено.
Начальный рендер
Когда ваше приложение запускается, вам нужно запустить первоначальный рендеринг. Фреймворки и песочницы иногда скрывают этот код, но это делается путем вызоваcreateRoot
с целевым узлом DOM, а затем вызова его метода рендеринга с вашим компонентом:
// index.js import Image from './Image.js'; import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')); root.render(<Image />);
// Image.js export default function Image() { return <img src="https://example.com/image.jpg" alt="image" />; }
Рендеринг при обновлении состояния
После первоначального рендеринга компонента вы можете запускать дальнейшие рендеры, обновляя его состояние с помощью функцииset
. Обновление состояния вашего компонента автоматически ставит рендеринг в очередь. (Вы можете представить это как гостя ресторана, который заказывает чай, десерт и другие блюда, после того как сделал свой первый заказ, в зависимости от состояния жажды или голода.)
Шаг 2: React визуализирует ваши компоненты
После запуска рендеринга React вызывает ваши компоненты, чтобы выяснить, что отображать на экране. «Рендеринг» — это React, вызывающий ваши компоненты.- При первоначальном рендеринге React вызовет корневой компонент.
- Для последующих рендеров React будет вызывать функциональный компонент, обновление состояния которого инициировало рендеринг.
Gallery()
и Image()
несколько раз:
// Gallery.js export default function Gallery() { return ( <section> <h1>Inspiring Sculptures</h1> <Image /> <Image /> <Image /> </section> ); } function Image() { return <img src="https://example.com/image.jpg" alt="image" />; }
// index.js import Gallery from './Gallery.js'; import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')); root.render(<Gallery />);
- Во время первоначального рендеринга React создаст узлы DOM для тегов
<section>
,<h1>
и трех тегов<img>
. - Во время повторного рендеринга React вычислит, какие из их пропсов, если таковые имеются, изменились с момента предыдущего рендеринга. Он ничего не будет делать с этой информацией до следующего шага, фазы фиксации.
- При тех же входах, тот же выход. При одинаковых входных данных компонент всегда должен возвращать один и тот же JSX. (Когда кто-то заказывает салат с помидорами, он не должен получать салат с луком.)
- Он думает только о своих делах. Он не должен изменять какие-либо объекты или переменные, существовавшие до рендеринга. (Один заказ не должен изменять чей-либо другой заказ.)
Оптимизация производительности
Поведение рендеринга по умолчанию всех компонентов, вложенных в обновленный компонент, не является оптимальным для производительности, если обновленный компонент находится очень высоко в дереве. Если вы столкнулись с проблемой производительности, существует несколько способов ее решения, описанных в разделе «Производительность». Не оптимизируйте преждевременно.Шаг 3: React фиксирует изменения в DOM
После рендеринга (вызова) ваших компонентов React изменит DOM.- Для начального рендеринга React будет использовать DOM API
appendChild()
для размещения на экране всех созданных DOM-узлов. - Для повторного рендеринга React применит минимально необходимые операции (рассчитанные во время рендеринга), чтобы привести DOM в соответствие с последним результатом рендеринга.
<input>
, обновив его значение, но текст не исчезнет при повторном рендеринге компонента:
Это работает, потому что на этом последнем шаге React только обновляет содержимое// Clock.js export default function Clock({ time }) { return ( <> <h1>{time}</h1> <input /> </> ); }
<h1>
новым значением времени. Он видит, что <input>
появляется в JSX в том же месте, что и в прошлый раз, поэтому React не касается <input>
или его значения.
Отрисовка браузером
После того, как рендеринг завершен и React обновил DOM, браузер перерисует экран. Хотя этот процесс известен как "рендеринг в браузере", мы будем называть его "отрисовкой", чтобы избежать путаницы в остальной части этого руководства.Резюме
Любое обновление экрана в приложении React происходит в три этапа:- Запуск
- Рендеринг
- Фиксация
JavaScript в фигурных скобках в JSX в React компонентах
год назад·3 мин. на чтение
JSX позволяет вам писать HTML-подобную разметку внутри файла JavaScript, сохраняя логику рендеринга и содержимое в одном месте. Иногда вам может понадобиться добавить немного логики JavaScript или сослаться на динамическое свойство внутри этой разметки. В этой ситуации вы можете использовать фигурные скобки в JSX, чтобы добавить в них JavaScript.
Содержание туториала по React
JSX позволяет вам писать HTML-подобную разметку внутри файла JavaScript, сохраняя логику рендеринга и содержимое в одном месте. Иногда вам может понадобиться добавить немного логики JavaScript или сослаться на динамическое свойство внутри этой разметки. В этой ситуации вы можете использовать фигурные скобки в JSX, чтобы добавить в них JavaScript.
Передача строк в кавычках
Когда нужно передать строковый атрибут в JSX, нужно заключить его в одинарные или двойные кавычки:Здесьexport default function Avatar() { return ( <img className="avatar" src="http://example.com/userpic.jpg" alt="User Name" /> ); }
"http://example.com/userpic.jpg"
и "User Name"
передаются как строки.
Но что, если вы хотите динамически указать src
или alt
? Вы можете использовать JavaScript значение, заменив "
и "
на {
и }
:
Обратите внимание на разницу междуexport default function Avatar() { const avatar = 'http://example.com/userpic.jpg'; const description = 'User Name'; return <img className="avatar" src={avatar} alt={description} />; }
className="avatar"
, который указывает имя CSS класса "avatar"
, и src={avatar}
, который считывает значение переменной JavaScript с именем avatar
. Это потому, что фигурные скобки позволяют вам работать с JavaScript прямо в разметке.
Использование фигурных скобок: JavaScript в разметке
JSX — это особый способ написания JavaScript. Это означает, что внутри него можно использовать JavaScript — с помощью фигурных скобок{
}
. В приведенном ниже примере сначала объявляется имя, name
, а затем оно встраивается в фигурные скобки внутри <h1>
:
Любое выражение JavaScript будет работать между фигурными скобками, включая вызовы функций, таких какexport default function TodoList() { const name = 'User Name'; return <h1>{name}'s To Do List</h1>; }
formatDate()
:
const today = new Date(); function formatDate(date) { return new Intl.DateTimeFormat('en-US', { weekday: 'long' }).format(date); } export default function TodoList() { return <h1>To Do List for {formatDate(today)}</h1>; }
Где использовать фигурные скобки
Вы можете использовать фигурные скобки только двумя способами внутри JSX:- Как текст непосредственно внутри тега JSX:
<h1>{name}'s To Do List</h1>
работает, но<{tag}>To Do List</{tag}>
работать не будет. - Поскольку атрибуты следуют сразу после знака
=
:src={avatar}
будут считывать переменнуюavatar
, ноsrc="{avatar}"
передаст строку"{avatar}"
.
Использование двойных фигурных скобок: CSS и другие объекты в JSX
Помимо строк, чисел и других выражений JavaScript, вы даже можете передавать объекты в JSX. Объекты также обозначаются фигурными скобками, например{ name: "User Name", itemsCount: 10 }
. Следовательно, чтобы передать объект JS в JSX, вы должны заключить объект в другую пару фигурных скобок: person={{ name: "User Name", itemsCount: 10 }}
.
Вы можете увидеть это со встроенными стилями CSS в JSX. React не требует от вас использования встроенных стилей (классы CSS отлично подходят для большинства случаев). Но когда вам нужен встроенный стиль, нужно передать объект атрибуту стиля:
Встроенные (inline) стили записываются в camelCase. Например, HTMLexport default function TodoList() { return ( <ul style={{ backgroundColor: 'black', color: 'pink', }} > <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> ); }
<ul style="background-color: black">
в компоненте будет записан как <ul style={{ backgroundColor: 'black' }}>
.
Другие примеры JavaScript объектов в фигурных скобках
Вы можете переместить несколько выражений в один объект и ссылаться на них в JSX внутри фигурных скобок:В этом примере объект JavaScriptconst person = { name: 'User Name', theme: { backgroundColor: 'black', color: 'pink', }, }; export default function TodoList() { return ( <div style={person.theme}> <h1>{person.name}'s Todos</h1> <img className="avatar" src="https://example.com/userpic.jpg" alt="userpic" /> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </div> ); }
person
содержит строку имени и объект темы:
Компонент может использовать эти значения изconst person = { name: 'User Name', theme: { backgroundColor: 'black', color: 'pink', }, };
person
следующим образом:
JSX очень минималистичен как язык шаблонов, потому что он позволяет вам организовывать данные и логику с помощью JavaScript.<div style={person.theme}> <h1>{person.name}'s Todos</h1>
Резюме
Теперь вы знаете почти все о JSX:- Атрибуты JSX внутри кавычек передаются как строки.
- Фигурные скобки позволяют добавить в разметку логику и JavaScript переменные.
- Они работают внутри содержимого тега JSX или сразу после
=
в атрибутах. {{
и}}
не являются специальным синтаксисом: это объект JavaScript, спрятанный внутри фигурных скобок JSX.