От автора: я был немного вдохновлен этим утром твиттом от Кента Си Доддса. Признание: мне сегодня немного тоскливо, к тому же у меня небольшое похмелье, поэтому прошу прощения, если буду выражаться не слишком четко.. Но я увидел, что в списке Кента присутствует один пункт: vanilla javascript!
Итак, давайте сделаем это самым простым способом:
Это работает, но это немного скучно и не очень масштабируемо. Состояние хранится в DOM, что является шаблоном, который мы оставили в 2000-х годах, и вам придется копировать и вставлять его для повторного использования в любом месте.
Что, если бы мы взяли за образец React и превратили это в компонент многократного использования, а также выделили состояние из логики рендеринга?
Это немного ближе к тому, что мы хотели бы достичь. Но после использования JSX вызов вручную document.createElement и element.appendChild кажется неоптимальным.
К счастью, JSX фактически полностью независим от React. Вы можете буквально написать свой собственный JSX-рендерер и указать babel использовать его с помощью комментария /* @jsx myRenderer */. Очень просто написать рендерер, который превращает JSX в простые старые элементы DOM:
Эта реализация jsxToDom оставляет желать лучшего, и почти не покрывает граничные случаи, поэтому мы не можем сказать, что она готова к производству. Но для данного примера это подходит; мы создаем узел DOM со всеми нужными атрибутами и прослушивателями событий, что означает, что нам не нужно делать это вручную.
Кстати, это шаблон, который мы используем в PayPal для zoid, когда хотим выполнить одноразовые рендеринги на сторонних сайтах, и не хотим доставлять полный движок компонентов, такой как React, или полную библиотеку шаблонов. С помощью JSX все шаблоны компилируются во время сборки на vanilla javascript, поэтому он такой компактный.
В любом случае — давайте используем эту новую прагму JSX jsxToDom.
Это намного чище, но здесь есть кое-что, что можно еще улучшить. Обновление DOM по-прежнему очень тесно связано с обновлением состояния. Мы должны вызывать updateButton вручную каждый раз при изменении state.count, что вызовет беспорядок, если мы представим больше обработчиков событий, изменяющих состояние.
В React это обрабатывается с помощью setState, который запускает повторную визуализацию в любое время, когда изменяется состояние. Можем ли мы сделать что-то подобное в vanilla javascript? Очень может быть!
Мы создали setState, поэтому вместо того, чтобы напрямую изменять состояние, он сопоставляет старое состояние с новым. Это намного ближе к React и намного более функционально. Эти вызовы setState также будут запускать любые обновления DOM.
Почему бы нам просто не выполнять полную повторную визуализацию при каждом изменении состояния? Это было бы проблематично, потому что пользовательский интерфейс должен был бы полностью сбрасываться после каждого обновления. Поля формы будут очищаться, и в целом опыт будет ужасным. Итак, чего нам не хватает по сравнению с React? Что ж:
Нам по-прежнему приходится отделять первоначальный рендеринг и последующие обновления / модификации пользовательского интерфейса при изменении состояния. React обрабатывает это, изменяя два виртуальных DOM и сопоставляя различия с реальным DOM — это означает, что ваш код может просто реализовать красивую однозадачную функцию рендеринга. Здесь мы не достигнем этого.
У нас есть способ передачи свойств компонентам для первоначального рендеринга, но нет способа обновления свойств через жизненный цикл приложения. Это, очевидно, важная часть построения масштабируемого приложения с использованием шаблона компонента. Может быть, есть чистый способ расширить этот шаблон, чтобы сделать это с помощью javascript. Но пока я оставляю это, как возможность для дальнейших упражнений читателя.
Также нет других хуков жизненного цикла, которые предоставляет React, такие как componentDidMount или componentDidUpdate, но у нас есть их аналоги; компонент устанавливается, когда основная функция вызывается в первый раз, а mutator вызывается при обновлении состояния.
React загружает обновления состояния, прежде чем выполнить повторную визуализацию. Это полностью достижимо здесь, но для этого потребуется больше кода, а я хочу сохранить все максимально простым.
Могу ли я создать полноценное приложение, подобное этому для использования в производстве? Возможно нет. Но интересно, что мы можем ввести в свой код некоторую структуру и организацию, которые дает React, не используя сам React. Еще один урок состоит в том, что JSX можно использовать для любых общих шаблонов, даже вне React. Кто-нибудь хочет попытаться продолжить это?
Автор: Daniel Brain
Источник: https://medium.com/
Редакция: Команда webformyself.