Сегодня 520, это последняя статья в этой серии, в основном посвященная связанным сценариям управления состоянием React.
Предыдущие статьи вНаггетсОсновы первого релиза провалились в море, и читать особо нечего.Может статья слишком длинная? Наггетс слишком низкие? Или слишком много опечаток?Подумав об этом, написание для меня является процессом обучения и накопления, позволяющим мне научиться описывать вещь более всесторонне и систематически.Но написание действительно очень трудоемкий процесс Имеет значение, каждое предложение статьи необходимо тщательно обдумать, а также избегать излишней субъективности, чтобы не вводить других в заблуждение.
так подражать>Слоган компании: «Кто хочет смотреть, смотрит, кто не хочет — не смотрит».
Каталог серий
- 01 Проверка типа
- 02 Организация компонентов
- 03 Управление стилем
- 04 Компонентное мышление
- 05 Управление статусом
Каталог статей
- государственное управление
- вам не нужно государственное управление
- Вам не нужно сложное управление состоянием
- Redux
- Mobx
- RxJS
- Другие решения для управления состоянием
- Расширенное чтение
государственное управление
Одна из основных идей современных интерфейсных фреймворков, включая React, заключается в следующем.представление на основе данных, которыйUI = f(state)
, Изменение в этом методе разработки на самом деле связано с Virtual-DOM, что заставляет нас не заботиться о деталях работы базовой DOM браузера, а заботиться только о «состоянии (состоянии)» и «отображении состояния в пользовательский интерфейс». (е)'.Поэтому, если вы новичок и не можете понять, что такое «управление данными», не рекомендуется продолжать чтение следующего содержания статьи..
Но сstate
Сложность фреймворка, существующую компонентность фреймворка сложно контролироватьf
(Взаимосвязь отображения представлений становится сложной и трудной для выражения и поддержки); или связанные типы потока данных приложения по своей сути сложны, а взаимодействие между компонентами разнообразно, что трудно использоватьUI = f(state)
Эта связь выражена, или состояние компонента приложения слишком дискретно и требует единого управления и т. д. У нас есть потребность в управлении состоянием.
Наиболее простым решением для управления состоянием является многоуровневое управление, т. е. традиционноеMV*
Принципиальной разницы между режимами нет, и основная структура основного госуправления в основном такова:
В основном они содержат следующие характеристики:
-
Разделение вида и состояния, Менеджеры состояний хороши в управлении состояниями, поэтому они обычно управляют состоянием приложения вместе, и представление вырождается в анемичное представление (сосредоточенное только на отображении), что может упростить
f
отношения отображения, пустьUI = f(state)
Это выражение более основательно -
Изменение состояния ограничения. Редукс требует прохода
dispatch+reducer
, mobx требует использования функции изменения данныхaction
украсить или разместитьflow
функция, цель состоит в том, чтобы сделать изменения состояния в соответствии с предсказуемостью - Однонаправленный поток данных.数据流总是按照 Store -> View -> Store 这样的方式流动, 简化数据流
Однако в React так много вариантов управления состоянием, что их выбор может свести с ума, и вам нужно сбалансировать множество вещей:
- Объектно-ориентированный или функциональный или функционально-реактивный?
- Один магазин или несколько магазинов?
- Неизменяемые данные или изменяемые данные?
- Написание кода — это круто или пост-обслуживание — это круто?
- Свобода или ограничение?
- Сильная или слабая типизация?
- Нормализовать данные или денормализовать?
- React родной или сторонний?
- ...
вам не нужно государственное управление
Управление состоянием не требуется для большинства простых приложений, промежуточных и внутренних проектов. Честно говоря, эти приложения ничем не отличаются от традиционных веб-страниц. Каждая страница независима. Каждый раз, когда открывается новая страница, подтягиваются самые свежие данные, а добавление, удаление, изменение и проверка не более чем это. сценарии, состояние компонента React может быть удовлетворено, нет необходимости в управлении состоянием ради управления состоянием.Такие отдельные «статические» страницы, представляющие управление состоянием, перепроектированы.
Подумайте, могут ли эти подходы решить вашу проблему, прежде чем рассматривать возможность внедрения управления состоянием:
- Можно ли общаться между компонентами, повышая состояние?
- Если слоев слишком много, можно ли обмениваться данными через Context API?
- Можно ли поместить некоторое глобальное состояние в localStorage или sessionStorage?
- Можно ли обмениваться данными через внешних подписчиков на события?
- ...
Вам не нужно сложное управление состоянием
Рассмотрите возможность управления состоянием, если ваше приложение имеет следующие сценарии:
- Между компонентами требуется совместное использование состояния. Одни и те же данные должны реагировать на несколько представлений и изменяться несколькими представлениями.
- Необходимо поддерживать глобальное состояние и реагировать на представления при их изменении.
- Поток данных стал сложным, и компоненты React не могут справиться с ним сами по себе. например, совместная работа пользователей на разных страницах
- Состоянием приложения необходимо управлять единообразно. Например, для достижения сохранения, восстановления, отмены/повторения
- ...
Сначала определите, нужны ли вам сложные инструменты управления состоянием, такие как Redux и Mobx? В 2019 году многие из их функций могут быть заменены функциями, предоставляемыми самим React. С выпуском нового Context API в React 16.3 мы можем легко делать простые помимо управления государством, мы должныПриоритет этих оригинальных методов управления экологическим состоянием.
Например: просто используйте Context API для управления состоянием:
В последнее время хуки довольно хорошо используются (см. предыдущую статью:компонентное мышление), я просто хотел сделать менеджер состояний с Context API, а позже обнаружил, что кто-то уже давно это сделал:unstated-next, Код всего 38 строк (Hooks+Context), интерфейс очень простой:
В зависимости от гибкости хуков мы можем использовать их для многих вещей, ограниченных только воображением, например, для асинхронного сбора данных:
Или реализовать основной функционал Redux:
Подводя итог преимуществам использования хуков в качестве менеджера состояний:
- минималистский. как указано выше
-
компонуемость, хуки — это обычные функции, вы можете комбинировать другие хуки и другие
Hooks Container
В предыдущей статье упоминалось, что хуки пишутся и пишутся очень похоже на компоненты, а компоненты пишутся и пишутся очень похоже на хуки С точки зрения использования компоненты можно рассматривать как своего рода «особые» хуки. По сравнению с компонентами крючки имеют более гибкие композиционные характеристики. - во имя реакции, Совместное использование состояния компонентов на основе контекста, управление состоянием на основе хуков, этот метод достаточно общий.
- Многих гибких функций хуков достаточно, чтобы заменить большинство функций фреймворков вроде Mobx.
- Просто обычные компоненты React, которые можно отлаживать в инспекторе React.
- Строгая типизация
- Легче реализовать модульность (или фрактал) на основе Context API.
Моменты, на которые следует обратить внимание
- Нет внешнего состояния.Состояние находится внутри компонента, и нет возможности инициировать изменение состояния извне.
- Отсутствие ограничений Это хорошо и плохо Для команд и новичков отсутствие ограничений приведет к несовместимости стилей и не сможет контролировать рост энтропии проекта. Преимущество в том, что вы можете настроить свои собственные ограничения
- Оптимизация производительности. Необходимо учитывать проблемы с производительностью, вызванные изменениями контекста.
- Опыт отладки не так хорош, как Redux
- Без зеркалирования данных невозможно выполнить такие требования, как управление событиями.
- Нет богатой экосистемы Redux
Поэтому хуки Context+ можно использовать для удовлетворения простых требований к управлению состоянием, а для сложных требований по управлению состоянием по-прежнему необходимы профессиональные менеджеры состояний, такие как Redux и Mobx.
другие подобные программы
- unstatedпредшественник неуказанный-следующий, используя setState API
- react-hooks-global-state
расширять
- API React Context API - замена для redux?
- не указано: инструменты управления состоянием могут быть самыми простыми
Redux
unstated
Это минималистское решение для управления состоянием, и его автор также сказал не думатьunstateed — убийца Redux, не стройте на его основе сложные инструменты, т.е. не изобретайте велосипед. Так что, как правило, на этом этапе вы должны рассмотреть сложные структуры управления состоянием, такие как Redux, Mobx и Rxjs.
Redux — это фреймворк, которого нельзя избежать, изучая React.Хотя код Redux составляет всего более 100 строк, концепций много, а кривая обучения очень крутая.Просто прочитайте официальную документацию. Несмотря на то, что его реализация чиста, код разработки не чист (в отличие от mobx, грязная работа остается за разработчиком), особенно следуя его «лучшим практикам», очень утомительно создавать проект с нуля. являются вторичными библиотеками-оболочками, такими как dva или rematch, чтобы упростить его.
В этой статье не ставится цель глубокого ознакомления с соответствующей практикой Redux. В сообществе есть много руководств, а официальные документы также очень подробны. Здесь мы представим основную архитектуру и основные идеи Redux, а также применимые к нему сценарии.
Основная структура Redux такая же, как указано выше. Перед этим вы должны выяснить, каково первоначальное намерение Redux, прежде чем вы сможете понять, почему он разработан таким образом. На мой взгляд, Redux в основном предназначен для решения следующих двух проблем:
- предсказуемое состояние
- Упрощение потока данных приложения
На самом деле это тожеflux
Первоначальный замысел Redux, но некоторые вещи сделаны не очень хорошо Поймите первоначальный замысел Redux, и теперь взгляд на его дизайн станет намного яснее
-
единственный источник правды-> Предсказуемый, упрощенный поток данных: данные можно изменять только в одном месте
-
Это может упростить поток данных приложения.Решите путаницу традиционного потока данных с несколькими моделями (например, модель может изменять другие модели, а представление управляется несколькими моделями), делая изменения данных предсказуемыми и отлаживаемыми.
-
Изоморфная разработка приложений
-
Легко отлаживать
-
Простое зеркальное отображение данных. Возможна отмена и повтор действий, перемещение во времени, горячая перезагрузка, сохранение состояния и восстановление.
-
-
Однонаправленный поток данных-> Упрощенный поток данных, предсказуемый
-
Состояние не может быть изменено напрямую-> предсказуемый
- Изменения состояния могут быть вызваны только отправкой действия. Действие — это просто объект, который содержит тип события и полезную нагрузку.
- Редуктор получает действие и старое состояние, а редукция генерирует новое состояние Редуктор — это просто чистая функция, а редуктор-комбинатор может быть вложен для сокращения сложного дерева состояний.
- Неизменяемые данные.
- Тестируемый.
-
Нормализация и Денормализация.Store хранит только нормализованные данные, уменьшая избыточность данных. Данные, требуемые представлением, денормализованы такими средствами, как повторный выбор
-
Изоляция побочных эффектов с помощью промежуточного программного обеспечения-> предсказуемый Можно сказать, что основной концепцией Redux является редьюсер, но это чистая функция. Для достижения сложных побочных эффектов Redux предоставляет механизм промежуточного программного обеспечения, подобный Koa, для достижения различных побочных эффектов, таких как асинхронные запросы.Кроме того, механизм промежуточного программного обеспечения можно использовать для реализации общих бизнес-моделей и уменьшения дублирования кода.
-
Devtool-> Предсказуемо. Поток данных можно визуализировать с помощью инструментов разработчика
Когда следует использовать Redux?
Прежде всего предупреждение:You Might Not Need Redux, Redux не ваш первый выбор.
Когда нам нужно иметь дело со сложным состоянием приложения, а сам React не может вас удовлетворить. Например:
- Вам необходимо сохранить состояние приложения, чтобы вы могли восстановить приложение из локального хранилища или данных, возвращенных с сервера.
- Необходимо реализовать отмену и повтор этих функций
- Включить межстраничную совместную работу пользователей
- Когда состояние приложения сложное
- Когда поток данных сложен
- Многим несвязанным компонентам необходимо совместно использовать и обновлять состояние
- Внешнее состояние
- ...
Лучшие практики
Личноreact-boilerplateЭто шаблон проекта, который лучше всего соответствует официальным «лучшим практикам». Его рабочий процесс приложения выглядит следующим образом:
характеристика:
- Интегрируйте наиболее популярные решения экосистемы Redux:
immer
(неизменяемые изменения данных),redux-saga
(асинхронная обработка потока данных),reselect
(выбрать и сопоставить состояние, памятка поддержки, компонуемый),connected-react-router
(привязка реактивного маршрутизатора v4) - Разделите сагу и редуктор по страницам. См. ниже 👇 и структуру каталогов.
- Загрузка саги и редуктора по требованию (через replaceReducer)
- Разделите компоненты контейнера и компоненты представления
Давайте взглянем на структуру каталогов react-boilerplate, Это мой личный любимый метод компонентов проекта, организация очень ясна, и это очень полезно для справки.
/src
/components # 展示组件
/containers # 🔴容器/页面组件
/App # 根组件, 例如放置Provider和Router
/HomePage # 页面组件
index.js # 页面入口
constants.js # 🔴 在这里定义各种常量。包括Action Type
actions.js # 🔴 定义各种Action函数
saga.js # 🔴 redux-saga 定义各种saga方法, 用于处理异步流程
reducer.js # 🔴 reducer。 页面组件的reducer和saga都会按需注入到根store
selectors.js # 🔴 redux state映射和计算
message.js
Form.js # 各种局部组件
Input.js
...
/FeaturePage # 其他页面组件结构同上
...
/translations # i18n 翻译文件
/utils
reducerInjectors.js # 🔴reducer 注入器, 实现和页面组件一起按需注入
sagaInjectors.js # 🔴saga 注入器, 同上
lodable.js
app.js # 应用入口
i18n.js # i18n配置
configureStore.js # 🔴 创建和配置Redux Store
reducers.js # 🔴 根reducers, 合并所有'页面状态'和'全局状态'(如router, language, global(例如用户鉴权信息))
🤬 Начинайте ругаться!
-
Во-первых, основная библиотека Redux очень мала и предоставляет только механизмы диспетчеризации и редьюсера.Для обработки различных сложных побочных эффектов Redux отдается на аутсорсинг, предоставляя механизм промежуточного программного обеспечения.. В сообществе есть много решений, redux-promise, redux-saga, redux-observable... Ознакомьтесь с Redux'sэкосистема.
Преимущество промежуточного программного обеспечения Redux заключается в том, что оно очень хорошо масштабируется. Разработчики могут использовать промежуточное программное обеспечение для абстрагирования повторяющихся операций. Экология промежуточного программного обеспечения также процветает, но она не дружелюбна к новичкам..
Как минимум ТМ нужно разбираться в разных библиотеках.После горизонтального сравнения можно узнать,какой библиотеке нужно соответствовать?Ну давайте выберем redux-saga,у которой больше звезд. Позже другой великий человек сказал, что не стоит программировать на звезды, и лучше всего выбрать то, которое подходит вашей команде... Так что, прежде чем выбрать правильное решение, вам все же придется разобраться в различных решениях, верно?
Вот почему кривая обучения Vue относительно плоская. Это помогает нам сделать большой выбор и предоставляет краткие решения. Кроме того, предоставляется официальное руководство по стилю и лучшие практики. Эти варианты подходят для более чем 80% потребностей разработки. Разработчики могут сэкономить много времени и сосредоточиться по писательскому делу.Это то, что называется 'прогрессивный'Framework, для тех, кто не любит метания или новичков, помогаем выбрать, но это не помешает пройтись по продвинутым местам. Здесь вы можете почувствовать, что стили сообщества React и сообщества Vue совершенно разные.
Когда есть трудности с выбором, лучше посмотреть, как выбирают другие, например относительно влиятельная команда или популярный проект с открытым исходным кодом (типа два, матч-реванш), выбрать компромиссный план, а потом подробно изучить его.Самые популярные комбинации для Redux:
immer+saga+reselect
-
Два, слишком много шаблонного кода. Например, приведенный выше шаблон реакции включает пять файлов и должен определять различные типы действий, действие, редьюсер, сага, выбор, Поэтому, даже если вы хотите внести небольшое изменение состояния, вам нужно изменить несколько мест:
Я лично предпочитаю что-то вроде Vuex
Ducks
Стиль организации, действие, сага, редуктор и маппер под модулем организованы в один файл:Вторичная среда инкапсуляции Redux в основном использует аналогичный стиль, например
rematch
Эти вторичные среды инкапсуляции обычно выполняют следующие оптимизации (фактически их можно рассматривать как преимущества Vuex) для улучшения опыта разработки Redux:
- Организуйте свой код, используя стиль Ducks.aggregate децентрализованные редукторы, сага, действия...
- Упрощенный API
- Предоставляет простой в использовании модульный (или «фрактальный») механизм пространства имен.. Сам модуль поддерживает «изоляцию состояния», так что редюсер и сага модуля фокусируются только на собственном состоянии модуля. Кроме того, модуль также учитываетдинамическая нагрузка
- Встроенный механизм обработки побочных эффектов. Например, использование саги или редукционного обещания
- Упрощенная обработка неизменяемых данных. при использовании иммера
- Упрощенный редуктор. Redux имеет встроенный combReducers для объединения нескольких редюсеров.В редюсерах мы обычно используем операторы switch для получения действий и обработки изменений данных.На самом деле, это очень многословно писать.Vuex и эти фреймворки инкапсуляции неизменно используют форму ключ/значение., короче
- Упростить интерфейс подключения слоя просмотра. Такие коды, как упрощение mapProps, mapDispatch, также громоздки для написания.
-
3. Обеспечьте неизменяемость данных. В предыдущей статье также упоминалось, что setState очень многословен, чтобы обеспечить неизменность состояния, проще всего использовать оператор расширения объекта или массива, если сложнее, вы можете использовать Immutable.js, который требует небольшая стоимость обучения. К счастью, теперь есть погружение. , вы можете реализовать неизменяемые данные в соответствии с привычками манипулирования объектами Javascript
-
Четыре, государственный дизайн.
Типы данных обычно делятся наДанные доменаа такжеДанные приложения (или данные пользовательского интерфейса), При использовании Redux вам часто нужно учитывать, должно ли состояние быть локальным для компонента, или все состояние должно быть извлечено в Redux Store? Кажется более проблематичным поместить эти данные в Redux Store? Теперь, когда мы все используем Redux, не лучше ли не извлекать данные в Redux Store? У автора тоже такая путаница время от времени, и у вас тожеЖертвы лучших практик?
Я думаю, что можно рассмотреть следующие моменты:
- Данные домена или данные приложения?Данные домена обычно рекомендуется размещать в ReduxStore, мы обычно рассматриваем Redux Store как базу данных для хранения нормализованных данных.
- Будет ли состояние использоваться несколькими компонентами или страницами?Redux Store — это глобальное хранилище состояний, и, поскольку используется Redux, имеет смысл позволить Redux управлять состоянием нескольких компонентов.
- Нужно ли отражать государство?Если вашему приложению необходимо совершить «путешествие во времени (отменить/повторить)» или постоянство приложения, и это состояние необходимо восстановить, его следует поместить в хранилище Redux. Централизованное управление данными — сильная сторона Redux.
- Должно ли состояние охватывать жизненный цикл компонента?Поместите состояние в компонент локально, оно будет уничтожено вместе с компонентом. Если вы хотите, чтобы состояние охватывало жизненный цикл компонента, его следует поместить в родительский компонент или в Redux Store.Например, нужно ли сохранять отредактированные данные модального окна после закрытия
Принцип заключается в том, что то, что можно разместить локально, должно быть размещено локально.Компромисс между локальным и глобальным состоянием требует небольшого опыта разработки.
Кроме того, в качестве централизованного менеджера состояний, для удобочитаемости состояния (легче понять) и работоспособности (легче добавлять, удалять, проверять и изменять), проектирование структуры состояния также требует определенных усилий.Структура этой базы данных Метод проектирования тот же,Перед проектированием состояния необходимо прояснить взаимосвязь между различными объектами предметной области и найти баланс между сложностью/производительностью операций сбора и изменения данных..
Официально рекомендовано ReduxНормализованное состояние, сгладьте дерево структуры, уменьшите вложенность, уменьшите избыточность данных.То есть, как правило, более удобно обновлять и хранить.Что касается того, что нужно представлению, оно передается для повторного выбора этих библиотек для расчета, сопоставления и объединения..
Так что Redux не так прост, и, конечно, 80% веб-приложений не должны быть такими сложными.
-
В-пятых, неудобная машинописная печать.. Ни redux, ни вторичная среда инкапсуляции не особенно удобны для Typescript для выполнения вывода типов, особенно после добавления различных расширений. Вам может потребоваться явно аннотировать многие типы данных
расширение:react-redux-typescript-guide, rematch & Typescript
-
Шестерка, не фрактал (фрактал)
не видя@杨建峰Вот этотЗнать ответРаньше я не знал, что такое фрактал, могу только попытаться объяснить свое понимание фракталов:
В предыдущей статье также упоминалось «разделение логики и представления» и «разделение компонентов контейнера и компонентов представления», оба из которых взяты из лучших практик Redux.Redux — это «нефрактальная архитектура», как показано на рисунке ниже.При таком простом «горизонтальном многоуровневом» представления и логика (или состояния) могут повторно использоваться по отдельности, но в Redux сложно рассматривать их как одно целое. Общие компоненты для повторного использования:
Централизованное хранилище, а затем через механизм Connect состояние можно повторно использовать во всем приложении; состояние и поведение, извлеченные из компонента Dumb, также можно легко использовать повторноТеперь предположим, что вам нужно выделить один контейнер в независимое приложение, один контейнер не может работать независимо.В фрактальной архитектуре «приложение» состоит из более мелких «приложений», и «приложение» имеет свой собственный механизм состояния. Одно приложение может работать независимо или как подприложение.Например, архитектура Elm, создателя Redux:
Структура Магазина согласуется со структурой приложения, и каждый компонент Elm также является приложением Elm, включая полное действие, обновление, модель и представление, что позволяет повторно использовать отдельные приложения.Redux не связан с позиционированием самого Redux, это чистый менеджер состояний и не включает представление компонентов, поэтому он не может сформировать полный замкнутый цикл приложения, как elm и cyclejs.. На самом деле можно обнаружить, что сам компонент react является фрактальным, а компонент изначально представляет собой набор состояний и представлений.
Преимущество фрактала заключается в том, что он может обеспечить более гибкое повторное использование и комбинирование, а также сократить связующий код. Очевидно, что фреймворки, поддерживающие чистую фрактальную архитектуру, сейчас не популярны, вероятно, потому, что порог относительно высок. Лично я думаю, что отсутствие поддержки фракталов не является проблемой для Redux в разработке. Мы можем разделить Redux на несколько модулей с помощью «модульности» и поддерживать их независимо в нескольких контейнерах. Является ли он в какой-то степени фрактальным? Кроме того, горизонтальная изоляция пользовательского интерфейса и состояния также выгодна: например, пользовательский интерфейс будет меняться чаще, чем бизнес-состояние.
Лично я считаю, что дифференциация на этом уровне страницы в самый раз, как и удобство разделения труда. Например, у автора недавно был такой проект.Нам нужно преобразовать нативный Windows-клиент в электронную реализацию.Из-за проблем с ресурсами этот проект предполагает совместную работу двух команд.Для этого проекта Магазин приложений является уровнем интерфейса, а команда Windows отвечает за Здесь мы поддерживаем состояние и реализуем бизнес-логику, в то время как наша команда внешнего интерфейса отвечает за уровень представления Таким образом, Windows не нужно изучать React и отображение отображения, и нам не нужно относятся к их сложной бизнес-логике (нижний уровень по-прежнему использует C++ и предоставляет некоторые интерфейсы узлу)
Семь, могут быть проблемы с производительностью
- Часто задаваемые вопросы по Redux: производительность
- Будет ли дерево состояний в редуксе слишком большой проблемой производительности?
- Почему я перешел с Redux на Mobx
- Сравнение производительности Mobx и Redux
Суммировать
В этом разделе в основном представлена мотивация дизайна Redux и ряд дизайнов, основанных на этой мотивации, а затем представлены некоторые недостатки и лучшие практики Redux. Экология Redux очень процветающая.Если вы новичок или не хотите метаться, рекомендуется использовать вторичные фреймворки инкапсуляции, такие как Dva или rematch.Эти фреймворки обычно являются осаждением некоторых лучших практик Redux, уменьшая время метания. Конечно, это только начало, вам еще многое предстоит узнать об организации большого проекта.
Расширенное чтение
- Каковы недостатки ReduxТукао на Чжиху
- Болевые точки, анализ и улучшение управления состоянием Redux
- Каковы лучшие практики для Redux?
- Как оценить архитектуру управления потоками данных Redux?
- Что еще мы можем сделать с Redux в 2018 году?
- Модель управления состоянием Cycle.js
- Разрабатывайте комплексные SPA с Dva
- Redesigning Redux
- Официальная документация Redux
- редукционное тройное царство
Mobx
Mobx предоставляет отзывчивую систему, похожую на Vue.По сравнению с Redux, архитектура Mobx легче для понимания. Взгляните на официальное изображение:
-
отзывчивые данные, Первое использование
@observable
Преобразование данных в «отзывчивые данные», аналогичные данным Vue. При доступе к этим данным в каком-либо контексте (например, в вычисляемых, обернутых наблюдателем компонентах React, реакции) могут быть собраны зависимости, и связанные зависимости будут уведомлены об изменении этих данных.Двумя преимуществами отзывчивых данных являются: ① Упрощенная обработка данных (по сравнению с redux и setState) ② Точная привязка данных. Представления должны отображаться только тогда, когда данные действительно меняются. Чем меньше степень детализации зависимостей компонентов, тем больше может быть обновлено более детально
-
производная.
- производные данные. Mobx также рекомендует не помещать в состояние избыточные или производные данные, а вместо этого использовать
@computed
Вычислить производное состояние.Концепция вычисленного похожа на повторный выбор в Redux, который денормализует или агрегирует нормализованные данные. - Полученные побочные эффекты. При изменении данных вызываются побочные эффекты, зависящие от этих данных, включая «представления». Представления — это карты реактивных данных
- производные данные. Mobx также рекомендует не помещать в состояние избыточные или производные данные, а вместо этого использовать
-
изменение данных.mobx рекомендуется в
action/flow(异步操作)
Чтобы изменить данные в Redux, действие можно рассматривать как комбинацию диспетчеризации + редуктора в Redux. В строгом режиме mobx ограничивает изменения только функциями действия, что позволяет изменениям состояния иметь обратную силу.Рекомендуется изолировать побочные эффекты в функции потока, аналогично Redux-saga, используя генераторы для асинхронных операций и изоляции побочных эффектов.
Вышеизложенное является основной концепцией Mobx. Возьмем простой пример:
ноMobx не является фреймворком, он не говорит вам, как организовать ваш код, где хранить состояние или как обрабатывать события, как это делает Redux, и нет лучших практик. Преимущество в том, что вы можете компоновать проекты в соответствии с вашими предпочтениями, такими как Redux (Vuex), или вы можете использовать объектно-ориентированную организацию; недостаток в том, что если у вас нет соответствующего опыта, вы будете перегружены и не знаете, как это сделать. организовать код
Mobx обычно использует объектно-ориентированный способ организации Магазина, официальная документацияЛучшие практики для создания крупных масштабируемых и поддерживаемых проектовТакже представлен этот метод, который на самом деле является классическим шаблоном MV*:
src/
components/ # 展示组件
models/ # 🔴 放置一些领域对象
Order.ts
User.ts
Product.ts
...
stores/ # store
AppStore.ts # 应用Store,存放应用全局信息,如auth,language,theme
OrderStore.ts
RootStore.ts # 根Store,组合所有下级Store
...
containers/
App/ # 根组件
Orders/ # 页面组件
...
utils/
store.ts # store初始化
index.tsx
доменный объект
В объектно-ориентированной области слишком много существительных и понятий, и они относительно абстрактны. Пожалуйста, поправьте меня, если вы неправильно поняли. Давайте не будем обсуждать, что такое теоретический объект предметной области, а рассмотрим его как абстракцию бизнес-сущности в реальном мира в ООП, в частности, это может быть какMVC
М в схеме или объект, отображенный в базе данных в ORM.
Для сложных объектов предметной области он будет извлечен как отдельный класс, как в предыдущем примере.Todo
Класс, преимущество извлечения как класса заключается в том, что он инкапсулирован и может содержать связанные поведения, определения и ассоциации других объектов, что более выразительно, чем чистые объекты Недостатком является то, что его нелегко сериализовать
Поскольку они слабо связаны со страницами и могут повторно использоваться на нескольких страницах, они помещаются в корневой каталог.models/
Далее Объекты предметной области на уровне кода имеют следующие характеристики:
- Определены некоторые поля (@observable) и некоторые методы работы (@action) некоторых объектов домена, а также могут быть связаны другие объекты домена, например заказы, связанные с пользователями и продуктами.
- Жизненный цикл управляется Магазином, или Магазин является контейнером Модели, что эквивалентно базе данных, Магазин обычно представляет собой синглтон
Пример
import { observable } from 'mobx';
export default class Order {
public id: string;
@observable
public name: string;
@observable
public createdDate: Date;
@observable
public product: Product;
@observable
public user: User;
}
Store
Хранилище — это просто контейнер модели, который отвечает за управление жизненным циклом объектов модели, определение производных состояний, инкапсуляцию побочных эффектов, интеграцию с внутренними интерфейсами и т. д. Хранилища, как правило, являются синглтонами.В приложениях Mobx они обычно делятся на несколько магазинов с разными привязками.страница.
Пример
import { observable, computed, reaction } from 'mobx';
export default class OrderStore {
// 定义模型state
@observable orders: Order[] = [];
_unSubscribeOrderChange: Function
rootStore: RootStore
// 定义衍生数据
@computed get finishedOrderCount() {}
@computed get finishedOrders() {}
// 定义副作用衍生
subscribeOrderChange() { this._unSubscribeOrderChange = this.orders.observe((changeData) => {} }
// 定义action
@action addOrder (order) {}
@action removeOrder (order) {}
// 或者一些异步的action
async fetchOrders () {
const orders = await fetchOrders()
orders.forEach(item => this.addOrder(new OrderModel(this, item)))
}
// 初始化,初始化数据结构,初始化订阅等等
initialize () {
this.subscribeOrderChange()
}
// 一些清理工作
release () {
this._unSubscribeOrderChange()
}
constructor(store: RootStore) {
// 和rootStore进行通信
this.rootStore = store
}
}
корневой магазин
class RootStore {
constructor() {
this.appStore = new AppStore(this);
this.orderStore = new OrderStore(this);
...
}
}
<Provider rootStore={new RootStore()}>
<App />
</Provider>
посмотри на одинРеальные примеры
Эта традиционная организация MVC имеет следующие преимущества:
- Легко понять и легко использовать, Мы знакомы с классическим шаблоном MVC и объектно-ориентированным.Особенно бэкенд-разработчики, знакомые с традиционными парадигмами объектно-ориентированного программирования, такими как Java.Для кросс-командного проекта, упомянутого выше, мы выбрали mobx в качестве состояния менеджер , что является лучшим способом для них понять. НоТребуется небольшой опыт для разделения и проектирования объектов домена и хранилищ доменов.
- Строгая типизация
- код краткий. Относительно избыточного кода шаблона Redux
- инкапсуляция данных. Структуры данных, выраженные с помощью классов, могут инкапсулировать соответствующее поведение.
вопрос
- Трудно обмениваться данными между несколькими магазинами, Наш подход заключается в том, чтобы позволить всем магазинам наследовать родительский класс в качестве посредника и передавать данные между несколькими магазинами через режим подписки на события.
- отсутствие организации. По сравнению с Redux, состояние слишком разбросано и ничем не ограничено, и состояние может быть изменено по желанию. Много нашего кода такое, лень писать действия, или даже присваивать значения состоянию прямо на слое представления, поэтому обязательно запускайте строгий режим
- нет магииЭто палка о двух концах.В Redux есть промежуточный механизм, который может расширять и абстрагировать многие повторяющиеся задачи, такие как добавление состояния загрузки в асинхронные методы, но он не дружелюбен к Typescript; решениям на основе классов не с чего начинать, и код будет более многословным, но более интуитивным
- Нет моментального снимка данных, не может реализовать откат по времени, в чем сильная сторона Redux, но большинству приложений эта функция не нужна, кроме того, ее можно реализовать через mobx-state-tree
- Не удается выполнить горячую перезагрузку
Также есть некоторые проблемы с самим mobx, о которых также говорилось в предыдущей статье, а также вы можете прочитать эту статью (Прекрасная беседа с интерфейсной средой потока данных Mvvm):
-
Инвазивный компонентПервоначальная структура компонентов React должна быть изменена. Например, все компоненты, которые должны реагировать на изменения данных, должны быть украшены наблюдателем.Локальное состояние компонентов также должно быть украшено наблюдаемыми, а также методами манипулирования данными и т. д. Связь с mobx глубокая, и в будущем фреймворк будет изменен или подвергнут рефакторингу.
-
совместимость, Рефакторинг с использованием прокси после mobx v5, но прокси не поддерживается до Chrome 49. Если вы хотите быть совместимым со старыми браузерами, вы можете использовать только v4, v4 имеет некоторыеяма, новичкам, не знающим mobx, сложно найти эти ямки:
- Наблюдаемые массивы не являются реальными массивами. Например, компонент таблицы antd не распознает массив mobx и должен быть преобразован между компонентами с использованием срезов.
- Добавление свойств в существующий наблюдаемый объект не захвачен автоматически
MV*
Только один из основной организации Mobx, многие статьи часто станутФункциональный и объектно-ориентированныйобсудить, а затем сделать вывод, что Redux лучше подходит для больших проектов,Основная причина такого вывода заключается в том, что в Redux больше ограничений (только один способ сделать это), что подходит для развития проекта и совместной работы в команде, а не для функционального и объектно-ориентированного.. Конечно, и функциональная, и объектно-ориентированная парадигмы имеют свои области знаний, например, функциональная подходит для обработки данных и абстракции сложных потоков данных, а объектно-ориентированная подходит для абстракции бизнес-модели.
Другими словами, подходит ли он для крупномасштабных проектов — это проблема организации проекта, и Mobx не предлагал никаких решений и лучших практик на ранней стадии. Это было позже развито его автором.mobx-state-treeЭтот артефакт, как библиотека построения модели состояния, предоставляемая MOBX, MST вбирает в себя преимущества REDUX и других инструментов.Преимущества обоих в сочетании с неизменяемыми данными/функциональными возможностями, прослеживаемостью, возможностью обнаружения/просмотра и инкапсуляцией, предоставляет множество полезных функций, таких как зеркалирование данных (путешествие во времени), горячая перезагрузка, промежуточное ПО для действий, интегрированные инструменты разработки Redux и строгая типизация (Typescript + проверка во время выполнения (спорный вопрос)), на самом деле это больше похоже на backend ActiveRecord Этот тип инструмента ORM строит граф объектов.
Типичный код:
В связи с тем, что у автора нет большой практики работы с MST, а объем статьи и без того очень большой, я не буду ее расширять, и у меня будет возможность поделиться ею позже.
Все еще есть следующий вывод, выбрать Mobx или Redux?Вот еще цитата изMobX против Redux: сравнение противоположных парадигм — Протокол React Conf 2017Заключение:
- Небольшие команды, которым необходимо быстро разрабатывать простые приложения, могут рассмотреть возможность использования MobX, поскольку MobX требует разработки небольшого объема кода, низких затрат на обучение и быстрого старта.Он подходит для систем реального времени, информационных панелей, текстовых редакторов и программного обеспечения для презентаций. , но не подходит для программного обеспечения, основанного на событиях.
- Redux подходит для больших команд для разработки сложных приложений.Redux может поддерживать совместную работу нескольких человек и меняющиеся бизнес-требования с точки зрения масштабируемости и удобства обслуживания.Он подходит для бизнес-систем, систем на основе событий и игровых сценариев, включающих сложные реакции.
Основным основанием для приведенного выше вывода является то, что Redux реагирует на действия/события, а MobX реагирует на изменения состояния. Например, когда изменение данных включает в себя несколько хранилищ Mobx, это может отражать то, как Redux более элегантен, а поток данных понятнее. Преимущества и недостатки Mobx и Redux были подробно описаны выше. Mobx также имеет благословение MST. Я верю, что у читателей уже есть это в сердце.
расширять
- Вам нужен Mobx или Redux?
- Принцип реализации идеи Mobx и сравнение с Redux
- MobX против Redux: сравнение противоположных парадигм — Протокол React Conf 2017
- dobБолее легкие колеса, похожие на mobx.
- Решение для управления состоянием React, принятое во внешнем интерфейсе Jimeng: Rex
- Галантерея | Интерфейсная структура потока данных Mvvm
RxJS
Если ни один из упомянутых выше инструментов управления государством не может удовлетворить ваши потребности, ваш проект может быть сложнее, чем 99% проектов в стране, RxJS может вам помочь,RxJS отлично подходит для приложений со сложными асинхронными потоками событий., у автора мало практики в этой области, и рекомендуется глянутьСтатьи, связанные с Сюй Фэй, Кроме того, Redux (Redux-Observable) и Mobx действительно можно использовать с RxJS.
Другие решения для управления состоянием
- Apollo+GraphQL
- freactal
порекомендовать эту статьюState of React State Management for 2019