Как работают реактивные фреймворки

Без рубрики
А вы когда-нибудь задумывались, как работают React, Angular, Vue.JS? Могут ли они менять поведение браузера и почему немедленно стоит их изучить.

Реактивные фреймворки (React, Angular, Vue) используются в веб-разработке для написания интерактивных сайтов и веб-приложений. Их основная суть заключается в том, чтобы максимально упростить написание веб-приложения за счёт того, что веб-разработчику не нужно изобретать велосипед и каждый раз заново реализовывать такие тривиальные вещи, как роутинг, обработку форм, подгрузку контента по API т.д. Установив фреймворк, разработчик может сразу приступать к самоу сочному — проектированию дизайна, построению интерактивности и интеграции с API.

Основные вещи, которые умеет любой реактивный фреймворк, это:

  • Связка текста на сайте с содержимым реактивных переменных. То есть фреймворк обновляет текст на странице при каждом изменении переменной;
  • Показ/скрытие HTML-элемента в зависимости от значения переменной;
  • Автоматическая генерация таблиц/списков/каталогов за счёт встроенных циклов;
  • Запуск нативных CSS-анимаций тогда, когда это нужно. Например, для перехода между страницами сайта, уведомлений, всплывающих окон и т.д.;
  • Использование компонентов — когда повторяющиеся фрагменты вёрстки можно вынести в отдельный файл и использовать их в нужных местах на сайте;

Реактивными эти фреймворки называются потому, что здесь используется модель MVC + интеграция с DOM в режиме реального времени. Простым языком это означает то, что при написании веб-приложения, разработчик никогда не обращается к HTML-элементам из скриптов напрямую. Вместо этого, вёрстка, стили и логика чётко разделены.

Живое обновление данных

See the Pen HowToReact / Реактивность 1 by Alexander Aleokheen (@aleokheen) on CodePen.

Первое, с чего начинается документация любого реактивного фреймворка — простой пример с текстовым полем, параграфом и переменной, которая объединяет (синхронизирует) текстовые значения в этих элементах.

Это реализуется проще простого: создаётся JavaScript объект, где наша переменная со значением является свойством объекта. На это свойство создаются геттеры и сеттеры. Каждый геттер в большнитсве случаев тупо возвращает наше значение и ничего с ним не делает. Сеттером же является функиция, которая берёт элемент из DOM и меняет там значение.

Теперь, для того, чтобы изменить значение в блоке, мы просто меняем значение свойства у нашего объекта. Согласитесь, чем-то напоминает первые уроки из Vue.

Директивы в HTML ({{username}})

See the Pen HotToReact / 2 by Alexander Aleokheen (@aleokheen) on CodePen.

В любом MVC фреймворке есть такая штука, как директивы. Это такие %username% штуки, куда скрипт вставляет информацию.

Директивы сами по себе работают очень просто; особенно — если не требуется реактивность. Достаточно пройтись регулярным выражением и заменить все %<название_поля>% на значения переменных.

В реактивных фреймворках всё сложнее. После первого рендеринга страницы (когда все директивы заменены на значения переменных), мы уже не можем искать директивы регулярным выражением, т.к. они уже все исчезли.

Здесь начинается одна из сложнейших, важнейших и основательных вещей любого реактивного фреймворка — работа с DOM. Чтобы понять представленный пример кода, необходимо знать особенности работы с браузерским DOM (в частности знание того, что такое HTML- или текстовая нода, как менять HTML-элементы местами и т.д.)

В представленном примере мы сделаем автоматическое создание геттеров и сеттеров для нашего объекта. Работу с DOM вынесем в отдельную функцию и будем вызывать её при изменении полей и при начальном рендереринге страницы.

Чтобы заменить директивы на нужные нам поля и, более того, сделать это всё реактивным, нам потребуется взять все текстовые ноды страницы, вырезать из них директивы и сделать их отдельными нодами. Далее мы просто меняем весь текст в самой ноде при изменении полей. Регулярные выражения используются только один раз при парсинге нод.

Работа с массивами

See the Pen LYNGJJY by Alexander Aleokheen (@aleokheen) on CodePen.

Увы, геттеры и сеттеры не умеют обрабатывать изменения в дочерних массивах и объектах. Если дело касается массивов, в JavaScript можно добавить геттеры/сеттеры в массив при помощи Proxy. Такое поможет при изменении существующих элементов массивов, а вот на методы push, unshift, pop и т.п такая штука не реагирует.

Что же делать в такой ситуации? Банально переписываем эти методы у массивов. Не обязательно трогать прототип класса Array, достаточно прописать локальные методы push/pop/unshift/shift в какой-то конкретный массив и по каждому методу вызывать необходимые хуки. Таким образом массив вновь становится реактивным.

Когда вы прогоняете ваш объект и автоматически ставите геттеры/сеттеры, вы можете сделать проверку на тип данных и, если это массив, прописать ему кастомные методы push/pop/unshift/shift. Если это объект, вызываете функцию рекурсивно для каждого дочернего объекта.

Здесь пример упрощён. Нет текстовых директив и объекта с геттерами/сеттерами. Здесь показан самый сок, который не запутает вас и поможет понять, как многое можно творить, если хорошо знать JavaScript.

Условные операторы (v-if)

See the Pen HowToReact / 3 by Alexander Aleokheen (@aleokheen) on CodePen.

Показ-скрытые элементов — одна из самых легчайших вещей, которую можно реализовать в реактивном фреймворке.

В представленном примере есть три текстовых блока. Два из них спрятаны (у них не стоит display: none; их вообще нет в DOM).

Когда мы нажимаем на кнопку, чтобы скрыть блок, мы просто заменяем его ноду на комментарий (или на что угодно), а чтобы показать блок — меняем ноду с комментарием на сам блок обратно.

Компоненты

Реактивные фреймворки удобны тем, что всю вёрстку можно поделить на отдельные компоненты (каждый хранится в своём файле). То есть меню сайта у нас в одном файле, боковая панель в другом, футер в третьем и т.д.

Каждый реактивный фреймворк реализовывает систему компонентов по своему. Например React использует JSX-синтаксис для своих компонентов.(подробнее об этом можно почитать здесь); Vue изначально принимает компонент как JS-объект с полями, где содержатся HTML, CSS и JS для компонентов. Что-то похожее делает и Angular.

Вся суть работы компонентов заключается в том, что любой HTML-элемент можно представить как JS-объект. Этот объект хранит свойства (они же атрибуты тега), массив дочерних элементов, события и некоторые другие парамет. Как работать с DOM, встраивать элементы друг в друга и т.д., вас научит любой обучающий ресурс по JavaScript.

Оцените статью