Следующий:
Лучшие практики для создания больших проектов с помощью mobx (2)
последовательность
mobx
Это адаптивная структура управления данными, основанная на шаблоне наблюдателя.redux
Это восходящая звезда.
Существует мнение, чтоmobx
Не подходит для строительства больших проектов из-заmobx
Слишком гибкие функции. Быть гибким означает быть свободным, что является ахиллесовой пятой при разработке крупных и все более сложных проектов.redux
В противном случае это единственный источник данных,reducer
чистая функция, толькоdispatch
Несколько функций, таких как статус модификации, обеспечивают высокую степень единообразия формата написания кода.
В этой статье не будет обсуждатьсяmobx
детали использования, будут использоваться только полностьюmobx
Исходя из преимуществ формат разработки унифицирован для обеспечения ремонтопригодности разработки масштабных проектов.
mobx
Преимущества чрезвычайно превосходны, объектно-ориентированное программирование, реактивное программирование,mutable
Метод обработки данных и возможность точного обновления компонентов здесь не обсуждаются.
недостатки мобкса
- 0. Данные могут быть определены где угодно. Может быть определен в компоненте вместо
state
роль; также может быть определена в отдельномstore
Внутри - 1. Логика взаимодействия с пользователем может быть написана в методе, объявленном компонентом, или в
store
внутри объявленного метода. - 2. Взаимодействие с пользователем часто включает несколько
store
обработка данных,store
Между ними может быть сформирована сеть перекрестных ссылок. - 3.
store
Часто разделенные на страницы и модули, разбросанные повсюду, нелегко управлять единообразно. - 4.
store
Инстанцированные время и путь не поддаются контролю. - 5, когда один пример
store
Поскольку бизнес-изменения должны поддерживать несколько экземпляров, преобразование чрезвычайно сложно. - 6. Не дружит с рендерингом на стороне сервера.
node
Когда терминал считывает данные для заполнения страницы, ему также необходимо сохранить данные на странице, чтобы внешний интерфейс мог восстановить данные из данных в исходное состояние.store
(redxu
изcreateStore
Естественная поддержка со стороныinitialState
возможность восстановления данных)
Столкнувшись с вышеуказанными проблемами, у большинства людей возникаетmobx
Виды не подходят для больших проектов.
решение
В авторском использованииmobx
+react
После выполнения многих средних и крупных интерфейсных проектов я ненавидел эти недостатки и постепенно исследовал некоторые решения для решения вышеуказанных проблем.
1. Наслоение
Для решения таких вопросов, как определение данных, совместное использование данных и предотвращение логического кода, структура проекта сначала состоит из нескольких уровней.
- Элементы разделены по страницам
- страница согласно
stores
,actions
,views
делится на три слоя -
stores
Определите методы работы каждой модели данных и данных на странице, и каждое хранилище не зависит друг от друга. -
views
слой как слой представления, получаяstores
Введенные данные отвечают за рендеринг -
actions
Слой обрабатывает логику взаимодействия, ссылаясь на каждыйstore
вызов метода для обновления данных иmobx
Автоматически активировать обновление представления
Вышеупомянутое является типичнымmvc
Иерархическая структура таким образом во многом решает проблемные пункты 0, 1, 2.
2. Единственный источник данных
На первом этапе трансформации ремонтопригодность проекта можно охарактеризовать как шаг вперед.
но страницаstore
а такжеaction
Необходимость вручную создавать экземпляры и вручную внедрять их в каждый компонент страницы — настоящее бремя. а такжеstore
Создание экземпляра бесплатное, а управление более запутанное. 3, 4 и 5 не решены.
Следовательно, необходимо разработать библиотеку управления состоянием, в основном реализующую следующие функции
-
store
а такжеaction
автоматическая загрузка поиска.store
а такжеaction
Размещены на страницах, просматриваются через какой-то механизм - все найдено
store
а такжеaction
Автоматически создавать и формировать глобально уникальный источник данных -
store
Предоставьте элементы конфигурации для настройки одного или нескольких экземпляров, чтобы уменьшить рабочую нагрузку по модификации кода из-за изменений в требованиях. - Создание экземпляра по запросу
store
. например, посещение страницыA
, просто создайте экземплярA
зависит от страницыstore
Найти механизм
store
а такжеaction
Есть два способа поиска, один черезwebpack
который предоставилrequire.context
Динамически импортировать файлы из определенного каталогаstore
а такжеaction
Модули, второй — загрузить через шаблон декоратора.
Псевдокод выглядит следующим образом
//webpack
require.context('./',true,/^(.+\/)*stores\/(.+)\.(t|j)sx?$/i)
//装饰器
@store({
path:'pageA.storeA', //在全局store中的访问路径
type:'singleton'|'multi' // 声明单例还是多实例
})
class StoreA{
}
// store装饰器的实现
let store = (config) => target => {
target['__storeType'] = config.type //保存
App['__stores'] = App['__stores'] || [] //App为状态管理类
App['__stores'].push({ target, path: config.path})
return target;
}
получить всеstore
После информации вы можетеstores
а такжеactions
Обрабатывай, собирай глобально уникальныеrootStore
сейчас,action
Обработка такая же.
Создание экземпляра по запросу
Если вы стремитесь к производительности, рассмотрите возможность реализации такой функции. Реализация может использовать атрибут доступа при доступе кstore
свойства, а затем динамическое создание экземпляров. Псевдокод выглядит следующим образом
Object.defineProperty(rootAction, 'storeA', {
configurable: true,
enumerable: true,
get() {
StoreA['__instance'] = StoreA['__instance'] || new StoreA()
return StoreA['__instance']
},
set() {
throw Error("can not set store")
}
})
Управление библиотекой через такое состояние, мы решили 3,4,5, 6 вопросов по рендерингу на стороне сервера, или простой обработкойrootStore
чтобы восстановить.
3. Оптимизация опыта разработки
(1) путь объявляется автоматически
декоратор сверху@store
нужно указывать вручнуюstore
существуетrootStore
Может ли узел вstore
Имя каталога, в котором находится файл, имя файла,store
Как насчет прямого сопоставления имен классов и другой информации с соответствующими структурами?
Ответ положительный, просто напишитеbabel
Плагин преобразования, который анализирует и заменяет абстрактное синтаксическое дерево файла во время компиляции и автоматически заполняет его.@store
изpath
свойства в порядке. (В авторском проекте используетсяts
при условииts transformer
выполнить ту же функцию)
(2) Леса
- Поскольку структура страницы остается очень однородной, независимо от того,
store
документ,action
файл илиjsx
,css
файл с более или менее шаблонным кодом. Чтобы автоматизировать процесс разработки, можно разработать инструменты формирования шаблонов для автоматического создания скелетов страниц. Один из них — повысить эффективность разработки, а другой — стандартизировать процесс разработки. - Если в проекте используется
ts
Если да, то эта глобальная автоматическая загрузка формируетсяstore
Информация о типе утеряна. Поэтому вам нужно автоматически сгенерировать файл объявления типа (.d.ts
), чтобы помочь получить лучший опыт разработки.
4. Ограничения спецификации разработки
Последняя тема — как более строго регламентировать способ написания кода.
Даже если мы ограничим бизнес-логику толькоaction
Это внутренне решается, но в конце концов это устная договоренность. Старые члены всегда имеют диаграмму, чтобы облегчить запись логики вview
Скорее всего, это произойдет с кодом, когда новый участник только что присоединился.
Таким образом, нам необходимо обеспечить механизм, гарантирующий, чтоaction
внутренний звонокstore
метод логической обработки, в то время как вaction
за пределамиstore
Вызовы недействительны, и в среде разработки выдается предупреждение.
Если вы думаете, что этот вопрос очень прост, это может быть потому, что вы не поняли его ключевой момент. Решение обсуждается ниже на примере.
//声明一个store
class StoreA{
age = null;
setAge(age){
this.age = age;
}
}
//声明一个action
class ActionA{
//调用store方法
setAge(age){
this.storeA.setAge(age); //有效
}
}
//组件内
storeA.setAge(age) //无效
Для приведенного выше сценария способ обработки относительно прост. нужно только
- объявить переменную
flag
- в инстанцировании
store
а такжеaction
При отдельном переносе методов экземпляра -
action
установить перед вызовом методаflag
дляtrue
,воплощать в жизньaction
метод, затем установитеflag
дляfalse
. - так
store
метод, если вaction
Доступ при вызовеflag
дляtrue
, доступ в другом местеflag
дляfalse
. - правильно
store
Упаковка метода относительно проста, судя поflag
,дляtrue
выполнять операции с данными дляfalse
Делайте дружеские советы
После вышеперечисленных шагов предельная обработка сцены синхронизации завершена.
Но в реальном проекте большое количество асинхронных операций, еслиaction
Как показано ниже, как это должно быть?
class ActionA{
//调用store方法
async setAge(age){
await saveAge(url); //接口调用
this.storeA.setAge(age); //有效
}
}
В настоящее времяstoreA.setAge
Хотя вaction
внутри, но доступ кflag
но этоfalse
, план провалился.
Хотя работать с синхронными операциями так просто, асинхронные операции представляют собой огромную проблему. Текущую тему можно абстрагировать следующим образом
如何实现在同一个方法内的调用(包括同步操作, setTimeout、promise、rAF、各种事件等异步操作的回调内...)都能访问到同一个上下文(true),而在这个方法外访问到的是另一个(false)
В сердце моем смутный ответ, если вaction
Сохраняйте этот контекст при вызове, а затем извлекайте этот контекст в различных асинхронных обратных вызовах для реализации функции. Но это ужасная вещь, а это значит, что нам нужно проксировать все асинхронные вызовы, другими словами, нам нужно переопределить нативный метод, чтобы сделать такое!
Это казалось трудным, пока я не узналzone.js
.
zone.js
Коротко представить,zone.js
даangular
основные компоненты каркаса,angular
использоватьzone.js
Прослушивайте все асинхронные события, которые могут привести к изменению данных.
Этот промежуток немного великоват, почему он появился снова?angular
.
Все в порядке, давайте снова представим его.zone.js
ОписаноJavaScript
Контекст процесса выполнения, который может постоянно передаваться между асинхронными задачами.
Дело в том, что это предложение, позвольте мне перевести его,zonejs
Может сохранять вызовы в рамках одного и того же метода (синхронного или асинхронного) с доступом к одному и тому же объекту контекста. Разве это не решает нашу проблему?
используй сейчасzonejs
решить нашу предыдущую задачу. код показывает, как показано ниже
//这里并没有阐述zone.js如何使用,如果看过zonejs文档应该很容易理解下面的代码所做的事情
const zone = Zone.root.fork({
name: '__mobx__zone'
});
//包装action的setAge方法,使得action内的方法调用访问到Zone.current都为zone
let oldFn = ActionA.setAge
ActionA.setAge = (...args) => {
return zone.run(oldFn, context, args)
}
//包装store的方法,判断Zone.current是否为zone,如果在action之外调用则为Zone.root
let oldFn = StoreA.setAge
StoreA.setAge = (...args) => {
if(Zone.current === zone){
return oldFn.apply(context,args)
}else{
//在action外调用store方法触发警告
console.error('invalid call')
}
}
//以上的包装方法均在内部处理,不暴露在业务代码中
использоватьzone.js
Мы легко реализуем нужные нам функции, которые можно найти при грубом просмотре исходного кода.zone.js
Это прокси насилия, котороеapi
.
С помощью вышеуказанных шагов мы можем с радостью принятьmobx
Создавайте и повторяйте большие проекты.
конец
В этой статье не содержится слишком много деталей кода, посколькуmobx
Как им пользоваться, тоже не поясняется. Данная статья посвящена решению проблемы использованияmobx
проблемы, которые могут возникнуть в процессе, и попытаться стандартизировать стиль кода членов, чтобы при использованииmobx
При разработке проекта можно в наибольшей степени гарантировать унификацию формата кода, а также снизить стоимость обслуживания проекта.
Как разработать и поддерживать крупномасштабный проект — большая тема, это должно быть сделано на основе заключения контракта или предписания определенных спецификаций, а затем создания конкретных проектов в соответствии с бизнес-сценарием, в котором он находится.