Самая главная причина почему современные JavaScript фреймворки существуют

Самая главная причина почему современные JavaScript фреймворки существуют

От автора: я видел, как много людей слепо используют современные JavaScript фреймворки React, Angular и Vue.js. В этих фреймворках много интересных вещей, но люди обычно упускают главную причину их существования.

Эта причина не связана с:

Они основаны на компонентах

У них сильное сообщество

У них много сторонних библиотек для работы

У них есть полезные сторонние компоненты

У них есть расширения для браузера для помощи с отладкой

Они хорошо подходят для создания одностраничных приложений

Главная, фундаментальная причина заключается в следующем:

Да, это правда. Давайте узнаем почему

Представьте, что вы реализуете веб-приложение, где пользователь может приглашать много людей через приглашения по email. UX/UI дизайнер принимает решение: у нас есть пустое состояние, где мы показываем лейбл с каким-то вспомогательным текстом, в противном случае мы показываем email адрес с кнопкой/ссылкой справа для удаления.

Состояние этой формы может представлять собой массив объектов, содержащих email адреса и уникальный идентификатор. По умолчанию он будет пустым. При добавлении email адресов путем их ввода и нажатия enter, введенный адрес добавляется в массив и обновляет UI. Когда пользователь кликает на delete, вы удаляете email адрес и обновляете UI. Видели? Каждый раз при смене состояния вам нужно обновлять UI.

И что из этого? Давайте посмотрим, как реализовать это без помощи фреймворков:

Чистая реализация любого сложного UI

Код отлично иллюстрирует, какую работу необходимо проделать ради такого сложного UI на чистом JS (с помощью классических библиотек типа jquery).

В примере статичная структура создается в HTML, а динамические вещи создаются в JS (с помощью document.createElement). Это первая проблема: JS код, создающий UI, не очень читаемый, и мы определяем UI в двух разных частях. Можно было бы использовать innerHTML, он был бы более читаемым. Но он менее эффективен и может вызвать баги Cross Site Scripting. Мы могли бы использовать и механизм шаблонов, но если мы регенерируем большое поддрево DOM, то получаем 2 проблемы: не очень эффективно, и часто приходится повторно подключаться к обработчикам событий.

Но это не главная проблема. Главная проблема всегда – это обновление UI каждый раз при изменении состояния. Каждый раз при изменении состояния в UI необходимо обновлять много кода. При добавлении email в примере выше обновление состояния занимает 2 строки кода, а обновление UI – 13 строк. А наш UI максимально прост!!

Код не только трудно писать и понимать, но более важно: он сильно замусорен. Представьте, нам нужно реализовать возможность синхронизации списка с сервером. Нам нужно сравнивать наши данные с данными, полученными с сервера. Для этого нужно сравнить все идентификаторы и контент (можно хранить в памяти копию записи с тем же идентификатором, но другими данными).

Специально для этого случая нам придется реализовать много кода представления, чтобы эффективно мутировать DOM. Если мы допустим минимальную ошибку, UI не будет синхронизирован с данными: потеря информации, показ неверной информации или полная поломка элементов не отвечают требованиям пользователя или даже хуже, вызывают неправильные действия (например, клик по delete удаляет не тот элемент).

Поэтому поддержание синхронизации UI с данными включает в себя написание большого утомительного и мусорного кода.

Декларативный UI в помощь

Ни сообщество, ни инструменты, ни экосистема, ни сторонние библиотеки…

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

Ну, почти. Это так, если вы не нарушите некоторые правила, которые могут быть у каждого конкретного фреймворка (например, неизменность состояния).

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

Как это работает?

Есть 2 базовые стратегии:

Повторный рендер всего компонента: React. Когда состояние компонента меняется, происходит рендер DOM в памяти и сравнение его с существующим DOM. На самом деле, это было бы очень затратно по производительности, поэтому рисуется Virtual DOM и сравнивается он с предыдущим снимком Virtual DOM. Затем происходит расчет изменений и выполнение тех же изменений в реальном DOM. Процесс называется согласованием.

Отслеживание изменений через observers: Angular и Vue.js. За переменными состояния ведется наблюдение, и когда они меняются, обновляются только элементы DOM, в которых эти значения включены или были включены в рендер.

А что с веб-компонентами?

Очень часто люди сравнивают React, Angular и Vue.js с web components. Это явный показатель того, что многие не понимают основного преимущества этих фреймворков: поддержание синхронизации UI с состоянием. Веб-компоненты ничего такого не дают. У них есть лишь тег template, но в нем нет никакого механизма согласования. Если вы хотите использовать веб-компоненты и поддерживать синхронизацию UI со внутренним состоянием приложения, вам придется делать это вручную или использовать что-то типа Stencil.js (он внутренне использует Virtual DOM, как React).

Но давайте проясним: в этих технологиях нет потенциала: нам нужно всегда синхронизировать UI с состоянием. По умолчанию веб-компоненты не дают ничего такого, и вам приходится использовать сторонние библиотеки (или делать вручную). Невозможно писать сложный, эффективный и легко обслуживаемый UI на чистом JS. Это главная причина, по которой вам необходим современный JS фреймворк.

Делайте сами

Я обожаю изучать основы, и, оказывается, существуют реализации Virtual DOM. Так почему бы не попробовать переписать наш чистый UI, но с реализацией Virtual DOM без помощи существующих фреймворков? Ниже представлено ядро фреймворка, базовый класс любого компонента.

Ниже показана переделанная реализация компонента AddressList (с помощью babel для поддержки JSX):

Теперь UI декларативный, и мы не использовали фреймворки. Мы можем реализовывать новую логику, которая меняет состояние любым способом, и нам не нужно писать дополнительный код для поддержания синхронизации с UI. Проблема решена!

За исключением обработки событий это похоже на приложение React? У нас есть haverender() ,componentDidMount() , setState()… После решения проблемы синхронизации UI с внутренним состоянием приложения, все остальное складывается самом собой.

Полный код можно найти на Github.

Заключение

Главная проблема, которую решают современные JS фреймворки – поддержание синхронизации UI и состояния

Невозможно писать сложный, эффективный и легко обслуживаемый UI на чистом JS

Веб-компоненты не решают эту проблему

Создать свой фреймворк с помощью библиотеки Virtual DOM не так и сложно. Но я не предлагаю вам делать этого!

Автор: Alberto Gimeno

Источник: https://medium.com/

Редакция: Команда webformyself.