Хуки React — это функция, появившаяся после волокна, поэтому многие люди ошибочно полагают, что для реализации хуки должны полагаться на волокно. На самом деле это не так. Это не обязательно связано.
Теперь хуки реализованы не только в React, но и в таких фреймворках, как Preact, React ssr и Midway. Их реализация не зависит от оптоволокна.
Давайте посмотрим, как реализованы хуки в этих различных фреймворках:
React описывает интерфейс через jsx, который будет скомпилирован в функцию рендеринга с помощью инструментов компиляции, таких как Babel или tsc, а затем выполнен для генерации vdom:
Функция рендеринга здесь была React.createElement до React17:
После React 17 он был изменен на jsx:
Эта jsx-среда выполнения будет добавлена автоматически, и нет необходимости сохранять импорт React для каждого компонента, как раньше.
Выполнение функции рендеринга генерирует vdom:
Структура vdom такая:
До React16 этот vdom отображался рекурсивно, добавляя, удаляя и изменяя реальный dom.
После того, как в React16 появилась архитектура волокна, был дополнительный шаг: сначала преобразовать vdom в волокно, а затем визуализировать волокно.
Процесс преобразования vdom в fibre называется согласованием, а окончательный процесс добавления, удаления и изменения реального dom называется фиксацией.
Зачем нам нужно такое преобразование?
Поскольку vdom имеет ссылки только на дочерние узлы и не имеет ссылок на родительский узел и другие одноуровневые узлы, это приводит к необходимости рекурсивно отображать все узлы vdom в dom одновременно без прерывания.
Что произойдет, если его прервать? Поскольку родительский узел и родственные узлы не записываются, мы можем продолжать обрабатывать только дочерние узлы, но не можем обрабатывать другие части vdom.
Вот почему React представил такого рода волоконную структуру, которая имеет такие ссылки, как возврат родительского узла, дочерний узел, родственный узел и т. д., которые можно прервать, поскольку все необработанные узлы могут быть найдены после прерывания и восстановления.
Структура оптоволоконного узла следующая:
Этот процесс можно прервать и, естественно, его можно запланировать, что является процессом планирования.
Таким образом, архитектура оптоволокна разделена на три этапа: планирование, согласование (преобразование vdom в оптоволокно) и фиксация (обновление до dom).
В функциональных компонентах можно использовать хуки для доступа к некоторым значениям, и эти значения хранятся на узле волокна.
Например, в этом функциональном компоненте используется 6 хуков:
Затем на соответствующем узле волокна имеется связанный список memorizedState из 6 элементов:
Объединено следующим:
Разные хуки получают доступ к значениям на разных элементах связанного списка memorizedState. Это принцип реагирования хуков.
Этот связанный список имеет этап создания и этап обновления, поэтому вы обнаружите, что окончательная реализация useXxx разделена на mountXxx и updateXxx:
Фаза монтирования здесь заключается в создании узлов-перехватчиков и их сборке в связанный список:
Созданный связанный список перехватчиков будет связан с атрибутом memorizedState узла волокна.
При обновлении вы можете естественным образом получить этот список перехватчиков из узла волокна:
Таким образом, при нескольких рендерингах API useXxx может найти соответствующий memorizedState на узле волокна.
Это принцип реагирования на крючки. Вы можете видеть, что он сохраняет крючок на узле волокна.
Так в чем же разница с preact?
Preact — это более легкая среда, совместимая с кодом реагирования. Она поддерживает компоненты классов и компонентов функций, а также такие функции реагирования, как перехватчики. Однако он не реализует волоконную архитектуру.
Потому что в основном учитывается максимальный размер (всего 3 КБ), а не максимальная производительность.
Мы только что узнали, что React хранит список перехватчиков на узле волокна. Если у Preact нет узла волокна, где будет храниться список перехватчиков?
На самом деле легко подумать, что Fiber только модифицирует vdom для повышения производительности, и существенной разницы с vdom нет. Тогда можем ли мы просто сохранить хук на vdom?
Действительно, preact помещает список перехватчиков на vdom.
Например, этот функциональный компонент имеет 4 хука:
Его реализация заключается в доступе к соответствующему хуку на vdom:
Он не делит хук на два этапа, монтирование и обновление, как реагирует, а объединяет их вместе для обработки.
Как показано на рисунке, он сохраняет хуки в массиве компонент.__hooks и получает к ним доступ через индексы.
Этот компонент является атрибутом vdom:
То есть значение хуков хранится в массиве vnode._comComponent._hooks.
Сравните различия между реагированием и preact при реализации перехватчиков:
в реакции список перехватчиков хранится в атрибуте fibreNode.memorizedState, в preact список перехватчиков хранится в атрибуте vnode._comComponent._hooks.
Список перехватчиков в реакции объединяется. через next и в preact. Связанный список с перехватом представляет собой массив.
React разделяет создание и обновление связанного списка
образом, реализация перехватчиков не опирается на оптоволокно, просто нужно найти место для хранения данных перехватчиков, соответствующих компоненту. Если их можно получить во время рендеринга, не имеет значения, где они хранятся.
Поскольку vdom, рендеринг волокон и компонентов тесно связаны, они хранятся в этих структурах.
Например, когда в реакции ssr реализованы перехваты, он не существует ни в оптоволокне, ни в vdom:
реакции
ssr
дом, когда csr:
При ssr используйте метод renderToString или метод renderToStream для реакции-дома/сервера:
Как вы думаете, будет ли преобразование vdom в оптоволокно во время SSR?
Определенно нет. Fiber — это структура, введенная для улучшения производительности рендеринга при работе в браузере, прерывания вычислений и выполнения вычислений в режиме ожидания.
Рендеринг на стороне сервера, естественно, не требует оптоволокна.
Если волокно не требуется, где оно хранит список крючков? вдом?
Его действительно можно поместить в vdom, но это не так.
Например, используйте хуки useRef:
Это связанный список, объединенный со списком next, начиная с firstWorkInProgressHook.
А firstWorkInProgressHook — это первый узел-перехватчик, созданный с помощью createHook:
Он не монтируется на vdom.
Почему?
Т.к. ssr нужно отрендерить только один раз и его не нужно обновлять, то и вешать его на vdom не нужно.
Просто очищайте список перехватчиков каждый раз, когда завершаете обработку перехватчиков каждого компонента:
Поэтому при использовании реакции ssr в глобальных переменных существуют хуки.
Сравните разницу в принципах реализации перехватчиков в реагировании csr и ssr:
в csr волокно будет создаваться из vdom, что используется для прерывания рендеринга и повышения производительности за счет планирования простоя, но в ssr оно не будет рендериться напрямую vdom. При использовании
csr хуки сохраняются в узле волокна, а при использовании ssr они помещаются непосредственно в глобальные переменные и очищаются после обработки каждого компонента. Поскольку CSR не будет использоваться второй раз
, создание и обновление хуков будет разделено на две фазы: монтирование и обновление, при этом SSR будет обрабатываться только один раз, и только фаза создания.
Принцип реализации хуков на самом деле не сложен. , то есть в определенном контексте сохраните связанный список в связанном списке, а затем API перехватчиков обращается к соответствующим данным из разных элементов связанного списка, чтобы завершить соответствующую логику. Этим контекстом может быть vdom, fibre или даже глобальная переменная.
Тем не менее, идея хуков по-прежнему очень популярна. Серверный фреймворк Midway, созданный Taobao, представил идею хуков:
Midway — это фреймворк Node.js:
Серверный фреймворк, естественно, не имеет таких структур, как vdom и fibre, но идея хуков на них не опирается. Чтобы реализовать API хуков, вам нужно всего лишь поместить связанный список в определенный контекст.
Midway реализует API, похожий на хуки реагирования:
Я не смотрел конкретно, где находится список хуков, но принцип реализации хуков мы уже освоили. Пока есть контекст для хранения списка хуков, он может быть где угодно.
что хуки реагирования — это функция, которая появилась после архитектуры React Fiber. Многие люди ошибочно полагают, что хуки должны быть реализованы с помощью Fiber. Мы рассмотрели реализацию хуков в React, Preact, React ssr и Midway соответственно и обнаружили, что. это не так:
. все будет в порядке. Итак, должны ли реагирующие крючки полагаться на волокно для его реализации?
Очевидно, нет, его можно использовать с оптоволокном, vdom, глобальными переменными или даже с любым контекстом.