Что такое реактивность¶
Введение¶
Реактивность - это основа интерактивности приложений Solid. В этой статье мы рассмотрим основы реактивности и то, как она работает в Solid.
Реактивность - это шаблон программирования, позволяющий настроить поведение, которое автоматически "реагирует" на изменение данных.
Например, можно сделать корзину покупок с ярлыком, на котором отображается общая стоимость товаров. С помощью реактивности можно указать, чтобы эта метка автоматически обновлялась при добавлении или удалении товара.
Таким образом, вам придется управлять только данными (например, добавлять товар в корзину). Как только вы соедините элементы пользовательского интерфейса (например, метку) с данными, обновление пользовательского интерфейса (изменение метки) будет выполнено за вас.
Чтобы начать работу с Solid, необходимо иметь базовое представление о реактивных сигналах и эффектах. В этой статье мы расскажем вам, как они работают за кулисами. Более глубокое понимание реактивности поможет вам оптимизировать код, отлаживать проблемы и создавать собственные расширения реактивной системы.
Реактивные примитивы¶
Чтобы использовать реактивность, вы создаете реактивные примитивы. Наиболее важными примитивами являются сигналы и эффекты. В следующих разделах мы объясним, что такое сигналы и эффекты, а затем сами реализуем их простую версию.
Другие реактивные примитивы
Solid имеет и другие реактивные примитивы, но они являются производными от сигналов и эффектов. Например:
- Хранилища - это деревья сигналов.
- Память - это сигналы, которые обновляются подобно эффектам
- Ресурсы - это сигналы, которые обновляются при получении данных с сервера
- Эффекты рендеринга - это эффекты, которые первоначально запускаются раньше.
Сигналы¶
Сигнал представляет собой часть данных, которая может изменяться. Например, сигналом может быть имя пользователя или значение счетчика, которое мы можем увеличивать. Сигналы состоят из двух основных частей:
- getter - функция, позволяющая получить доступ к текущему значению сигнала.
- setter - функция, позволяющая установить текущее значение сигнала.
Мы создаем сигнал с помощью функции Solid createSignal
. Она возвращает геттер и сеттер в виде двухэлементного массива. Обычно мы используем деструктуризацию массива, чтобы присвоить геттеру и сеттеру переменные с выбранными нами именами.
1 2 3 4 5 6 7 |
|
В этом примере count
- это геттер, а setCount
- сеттер.
Эффекты¶
Эффект представляет собой действие, которое мы хотим выполнить при изменении данных в одном или нескольких сигналах. Solid предоставляет функцию createEffect
, которая сама принимает функцию. Solid запустит эту функцию, а затем повторно запустит ее всякий раз, когда любой сигнал внутри этой функции изменит значение.
Например, следующий эффект будет console.log
подсчитывать счетчик при каждом его обновлении:
1 2 3 4 5 6 7 |
|
react
Обратите внимание, что в Solid не нужно указывать массив зависимостей для эффекта. Это основное отличие Solid от React — Solid будет автоматически отслеживать зависимости, а React - нет. Поэтому при повторном рендеринге компонента React повторно запускает любой эффект, если только разработчик явно не укажет зависимости.
Создание реактивной системы¶
Один из лучших способов понять, как работает реактивность, - это реализовать ее самостоятельно. В этом разделе мы реализуем тот же реактивный паттерн, который использует Solid: паттерн наблюдатель. В паттерне наблюдателя данные (сигналы) хранят список своих подписчиков (эффектов). При изменении данных сигнал вызывает всех своих подписчиков.
Используем для нашей реализации те же имена, createSignal
и createEffect
:
1 2 3 4 5 6 7 8 9 |
|
Сначала разберемся с основами функции createSignal
. Она должна:
- инициализировать значение
count
до0
(аргумент, передаваемый функцииcreateSignal
) - возвращать двухэлементный массив, состоящий из getter и setter функции
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Теперь мы можем получить текущее значение нашего сигнала, вызвав геттер, и установить его, используя сеттер. Это замечательно, но реактивности пока нет.
Далее давайте настроим createEffect
. Мы знаем, что он берет функцию и запускает ее:
1 2 3 |
|
Ключом к реактивности является установление взаимосвязи между createSignal
и createEffect
.
Для этого мы даем каждому сигналу список подписчиков. Когда мы даем createEffect
функцию и запускаем ее, мы хотим найти способ сказать всем сигналам, которые будут вызваны по пути, добавить эту функцию в их список подписчиков. Наши следующие шаги:
- Создать глобальный
currentSubscriber
, который будет следить за функцией, передаваемой вcreateEffect
. - Зарегистрировать функцию, которую мы передаем в
createEffect
, в качестве текущего подписчика - Когда мы обращаемся к сигналу, добавляем текущего слушателя в список подписчиков
- Когда мы устанавливаем сигнал в новое значение, запускаем всех подписчиков
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Это весь код, необходимый для создания базовой реактивной системы. Мы можем продемонстрировать, что она работает, увеличивая значение count
каждую секунду и наблюдая за консолью.
1 2 3 4 5 6 7 8 9 |
|
Мы только что реализовали самую базовую форму системы реактивности Solid!
Отслеживание эффектов синхронно¶
Следует отметить, что наша система реактивности является синхронной. Она глобально регистрирует подписчика, запускает эффект и снимает подписчика с регистрации.
Что же произойдет, если наша функция createEffect
будет выглядеть следующим образом?
1 2 3 4 5 |
|
Наша реализация createEffect
не ждет выполнения этого обратного вызова setTimeout
, поэтому к моменту вызова нашего геттера count
в глобальной области видимости нет подписчика. Сигнал count
не зарегистрирует этот обратный вызов в качестве одного из своих подписчиков.
Работа с асинхронными эффектами
Solid предоставляет некоторые возможности для работы с асинхронными эффектами. Например, можно использовать функцию on
для ручного указания зависимостей эффектов.
Более подробно о механизмах отслеживания, специфичных для Solid, можно узнать из документации Tracking Concept documentation.
Узнать больше¶
Мы надеемся, что вам понравилось это введение в реактивность! Если вы хотите углубиться в эту тему, ознакомьтесь со следующими ресурсами:
- Our Tracking Concept article
- A Hands-on Introduction to Fine-Grained Reactivity
- Building a Reactive Library from Scratch
- SolidJS: Reactivity to Rendering