Или просто хороший учебник по MobX
Framework Wars… НЕ
Я начал свое путешествие в сказочную страну Frameworks с Vue и этой удивительной серии от Laracast. Я слышал о React, но тогда, когда я смотрел на JSX, мне это показалось мерзостью! Смешивание тегов html с логикой JS? Разве они не слышали о шаблонах проектирования и разделении задач? Ради бога, почему бы просто не использовать JQuery для создания мигающего текста?
Но потом я изучил JS, а не JQuery JS * ( трюки с DOM), а JS как язык разработки, элегантный выразительный инструмент для управления данными, язык с красивыми методами для работы с массивами, Строка и объекты. И то, что вы не можете сделать с ванильным JS, скорее всего, для этого есть Lodash или наверняка есть пакет NPM. (npm install make-me-a-sandwich
Лол!)
После всего этого я еще раз взглянул на React и… я сразу влюбился! Где Vue похож на html с добавленной функциональностью (v-if, v-for...
), JSX - это простой JS, который генерирует DOM. На самом деле я не пытаюсь начать здесь войну фреймворков. В настоящее время у меня работают приложения Vue и React, и я смог найти все инструменты, которые мне нужны в обеих средах для выполнения моей работы. Выбор действительно сводится к личным предпочтениям или предпочтениям вашей компании / команды.
Но React ...
Для новичка в React казалось, что Redux - это хранилище по умолчанию, как и Vuex для Vue, поэтому я решил изучить Redux ... и, просмотрев полную серию статей о яйцеголовых примерно 3 раза и столько же раз просматривая документацию, я все еще чувствовал себя так, как будто я понятия не имел, что делаю. Написание чего-либо, кроме тривиального редуктора, было головной болью. Нормализованные данные, реляционные таблицы, неизменяемость и технология БД - все это казалось предварительными требованиями для Redux! Я многому научился, но не настолько, чтобы чувствовать себя хоть сколько-нибудь продуктивно. Затем есть обертки для Redux и функций высокого порядка для генерации других функций и рецептов редукторов ... Я снова почувствовал себя стажером, не имея возможности завершить свой проект, потому что я не знал, как создать простое хранилище и сделать свое приложение реагировать на это! 😥
Я уверен, что есть много разработчиков умнее меня, которые очень продуктивно работают с Redux. Я смотрю на тебя, сенсей!
Я пропустил дни Vuex, в которых все просто работало, изменяемое состояние не было грехом, и независимо от того, где я вызывал действие магазина, все приложение всегда было синхронизировано. Но мне тоже очень понравился React, поэтому я начал смотреть, могу ли я использовать Vuex на React (по-видимому, нет), но в поиске я наткнулся на MobX. У него были смелые претензии:
MobX снова упрощает управление состоянием, решая основную проблему: он делает невозможным создание несогласованного состояния. *
Я снова направился в яйцеголовый, чтобы посмотреть видеоуроки. Они были хорошими, но не повезло! create-react-app
не поддерживает декораторы, и вы не получите много примеров того, как что-то делать без них. Затем есть mobx-state-tree
, который утверждает, что он самоуверен (и это еще не все!), И опять же, я понятия не имел, как что-то делать и что происходит! Видео научили меня делать довольно приличный счетчик, и mobx-state-tree
казалось, что я пишу приложение для корпоративного банковского обслуживания, но я не мог найти средний уровень сложности.
Мне очень понравился React, поэтому я вернулся к Redux, но не смог заставить его работать, поэтому снова неохотно дал MobX еще одну попытку ... «И, наконец, я увидел свет; И туман рассеялся »
Хочу показать, что MobX проще в использовании, чем вы думаете. Мы собираемся использовать MobX, чтобы делать больше, чем просто считать вверх и вниз, и это проще, чем реализация mobx-state-tree
.
Магазин
Мы собираемся создать простой магазин, извлеченный из проекта, над которым я сейчас работаю. В нем у нас будет список студентов и список курсов, и мы сможем записывать и отменять студентов с курса.
Отправной точкой является чистое create-react-app
приложение, а вот store.js
:
🙄 Пусть вас не пугает длина, на самом деле это довольно просто, методы студентов и курсов одинаковы.
В терминологии MobX есть наблюдаемые, то, что отслеживается на предмет изменений, и наблюдатели, то, что которое следит за изменения. Оттуда остальное волшебство довольно волшебное!
Сначала мы просто объявляем const store
как первый параметр observable()
. * Вот как вы объявляете наблюдаемое без использования синтаксиса декоратора (@observable
).
Внутри объекта, переданного в observable()
, есть три места для размещения данных: студенты, курсы и зачисление, и они определены как observable.map()
. Если вы впервые сталкиваетесь с Картой, не волнуйтесь, это просто причудливый объект с удобным способом доступа к содержимому в нем (сеттеры и геттеры). В простом объекте JS доступ к данным осуществляется следующим образом: object.key1.key2
или object['key1']['key2']
. На карте доступ к ним осуществляется следующим образом: object.get('key1').get('key2')
. У этого есть несколько преимуществ, и в этом конкретном проекте это спасло меня от использования большого количества _.set()
и _.assign()
(от Lodash).
Затем идут методы магазина для добавления, обновления и удаления студентов и курсов из магазина. Они просто .set()
с некоторой обработкой ошибок.
Следующий интересный момент касается обработки регистрации. Эта идея определенно имеет привкус Redux (Отношения и таблицы), и в данном случае она полезна. Я создаю объект, ключ которого равен идентификатору курса, а значение представляет собой массив идентификаторов зачисленных студентов. Это выглядит так:
{ course1: ['student1', 'student2', 'student3'], course2: ['student4', 'student5', 'student6'], }
Действие происходит в методе enrolledStudents
. Давайте разберемся: он возвращает computed(() => {...})
функцию, которая представляет собой выражение MobX, которое отслеживает изменения в элементах внутри него и автоматически обновляет его значение. Ничего особенного. Затем он получает элемент в карте зачисления, который соответствует идентификатору курса, переданному в качестве аргумента, который возвращает массив идентификаторов студентов. Затем .map()
в массиве заменяет идентификатор каждого студента на весь объект ученика. Обратите внимание, что последний lonely .get()
применяется к computed()
и для получения фактических данных.
Таким образом, результатом метода enrolledStudents
является массив всех объектов студентов, зарегистрированных на конкретном курсе, извините, наблюдаемый массив , поэтому любые изменения данных внутри функции будут обновлять возвращаемое значение и выполнять соответствующие повторные отрисовки! 🤩
Вот простой компонент React, чтобы продемонстрировать это на практике:
Это довольно стандартные компоненты React, за исключением observer
и store
.
Сначала определяются и добавляются в магазин пара студентов и курс. Затем student1
зачисляется на курс. Затем мы сопоставляем метод enrolledStudents
из магазина, используя идентификатор курса для списка студентов, которых я хочу, и результаты ожидаются.
Самое интересное происходит, когда вы нажимаете кнопку «Зачислить студента 2».
В магазине идентификатор студента добавляется в массив соответствующей карты курса, и MobX заботится о том, чтобы все это синхронизировалось, правильно вычислить значение enrolledStudents
, и выполнить соответствующие повторные отрисовки. И все это происходит из-за L39, где мы оборачиваем StudentsList
внутрь observer()
!
Обратите внимание, что ваши компоненты могут получить доступ к магазину разными способами. Вы можете импортировать компонент из файла, как и в предыдущем примере, вы можете передать его как опору из родительского контейнера, или вы можете использовать утилиты mobx-react
provider / inject (в моем случае я могу импортировать store
всякий раз, когда Мне необходимо).
Заключение
MobX действительно кажется немного волшебным, и когда я наконец понял это, это было похоже на порыв свежего воздуха, ворвавшийся в мою разработку React! (это ссылка на верхнее изображение). Надеюсь, вам понравится его изучение, и вы продолжите делать крутые, классные вещи! 😎