Библиотека прогрессивного управления прогрессивным государством 1 КБ вдохновилась Vuex.
Вы можете получить эту библиотеку в качестве модуля Node.js, доступного через реестр NPM:
// With npm
$ npm install dragonbinder
// With yarn
$ yarn add dragonbinder Или вы можете использовать его отдельно в браузере с: <script src="https://cdn.jsdelivr.net/npm/dragonbinder"></script>
const Dragonbinder = require ( 'dragonbinder' ) ;
const store = new Dragonbinder ( {
state : {
count : 0
} ,
mutations : {
increment ( state ) {
state . count ++
}
}
} ) ;
store . commit ( 'increment' ) ;
console . log ( store . state . count ) // -> 1Dragonbinder Используйте прокси для создания состояния в качестве «единственного источника истины», который нельзя изменить, если вы не совершите мутацию. Это означает, что вы не можете удалить, изменить или добавлять свойство напрямую. Это позволяет нам отслеживать все изменения, которые мы внесли в штат.
Если вы не предоставите начальное состояние state имуществом Dragonbinder , создаст его.
const store = new Dragonbinder ( {
state : {
count : 0
} ,
mutations : {
addProperty ( state , value ) {
state . hello = 'world' ;
} ,
modifyProperty ( state ) {
state . count ++
} ,
removeProperty ( state ) {
delete state . count ;
}
}
} ) ;
// This will throw errors
store . state . hello = 'world' ;
store . state . count ++ ;
delete state . count ;
// This will work as expected
store . commit ( 'addProperty' ) ;
store . commit ( 'modifyProperty' ) ;
store . commit ( 'removeProperty' ) ;Кроме того, если вы хотите избежать одиноких, чтобы повторно использовать свое первоначальное определение магазина, вы можете объявить его состояние как фабричную функцию.
const myStoreDefinition = {
state ( ) {
return {
count : 1
}
} ,
mutations : {
increment ( state , payload ) {
state . count = state . count + payload ;
}
}
} ;
const store1 = new Dragonbinder ( myStoreDefinition ) ;
const store2 = new Dragonbinder ( myStoreDefinition ) ;
store1 . commit ( 'increment' , 5 ) ;
store2 . commit ( 'increment' , 3 ) ;
console . log ( store1 . state . count ) ; // -> 6
console . log ( store2 . state . count ) ; // -> 4Как и в случае с Vue, с Dragonbinder вы можете создавать Getters для создания вычисленных свойств на основе состояния. Этот добыт будет получать государство в качестве первого аргумента и всех других полученных, как второе.
const store = new Dragonbinder ( {
state : {
todos : [
{
content : 'First' ,
completed : false
} ,
{
content : 'Second' ,
completed : true
}
]
} ,
getters : {
completed ( state ) {
return state . todos . filter ( item => item . completed ) ;
} ,
completedCount ( state , getters ) {
return getters . completed . length ;
}
}
} ) ;
console . log ( store . getters . completed ) ; // -> { content: 'Second', completed: true }
console . log ( store . getters . completedCount ) ; // -> 1Мутации - единственный способ изменить состояние, и вы должны рассмотреть следующие моменты при разработке мутаций.
Object.freeze для предотвращения прямых изменений. Таким образом, когда вы меняете состояние, используя мутацию, вы можете добавлять, изменять или удалять только свойства первого уровня, свойства второго уровня будут считываться только. const store = new Dragonbinder ( {
state : {
hello : {
name : 'John Doe'
}
} ,
mutations : {
changeNameError ( state , payload ) {
state . hello . name = payload ;
} ,
changeNameOk ( state , payload ) {
state . hello = { ... state . hello , name : payload } ;
} ,
changeNameTo ( state , ... args ) {
state . hello = { ... state . hello , name : args . join ( ' ' ) } ;
}
}
} ) ;
// This will throw an assign to read only property error
store . commit ( 'changeNameError' , 'Jane Doe' ) ;
// This will work as expected
store . commit ( 'changeNameOk' , 'Jane Doe' ) ;
// You can pass any number of arguments as payload
store . commit ( 'changeNameTo' , 'Jane' , 'Doe' ) ;Если вам нужно обрабатывать асинхронные функции, вы должны использовать действия. И действия всегда будут возвращать обещание в результате их звонка.
const store = new Dragonbinder ( {
state : {
count : 0
} ,
mutations : {
increment ( state ) {
state . count ++
}
} ,
actions : {
increment ( state ) {
return new Promise ( ( resolve ) => {
setTimeout ( ( ) => {
store . commit ( 'increment' ) ;
resolve ( ) ;
} , 1000 ) ;
} )
}
}
} ) ;
store . dispatch ( 'increment' ) . then ( ( ) => console . log ( store . state . count ) ) ; // -> 1 after one secondВы можете зарегистрировать/отключить обратные вызовы на события.
const store = new Dragonbinder ( {
state : {
count : 0
} ,
mutations : {
increment ( state ) {
state . count ++
}
}
} ) ;
// Add a named listener
let namedListener = ( store , prop , newVal , oldVal ) => console . log ( `The property ${ prop } was changed from ${ oldVal } to ${ newVal } ` ) ;
store . on ( 'set' , namedListener ) ;
// Add an anonymous listener
let removeAnonymousListener = store . on ( 'set' , ( ) => console . log ( 'Anonymous listener triggered' ) ) ;
// Committing increment will trigger the listener
store . commit ( 'increment' ) ;
// $ The property count was changed from 0 to 1
// $ Anonymous listener triggered
// Remove a named listener
store . off ( 'set' , namedListener ) ;
// Remove an anonyous listener
removeAnonymousListener ( ) ;
// Committing increment will do nothing as the listeners are already removed
store . commit ( 'increment' ) ; Все события получают экземпляр магазина в качестве первого аргумента.
| Название события | Это вызвано, когда | Аргументы, полученные на месте |
|---|---|---|
| addlistener | Слушатель событий добавлен | Название события | Слушатель добавил |
| RemoveListener | Слушатель событий удален | Название события | Слушатель удален |
| набор | Свойство состояния добавлено или изменено, также запускается при зарегистрировании модуля | Название свойства | Новое значение | Старая стоимость |
| удалить | Свойство штата удаляется, также запускается, когда модуль незарегистрирован | Название свойства | Старая стоимость |
| BeforeCommit | Метод совершения и перед применением мутации | Мутационное имя | (...) Аргументы, переданные к мутации |
| совершить | Метод совершения вызова и после применения мутации | Мутационное имя | (...) Аргументы, переданные к мутации |
| Beforedispatch | Метод отправки вызвано и перед применением действия | Имя действия | (...) Аргументы, переданные в действие |
| отправлять | Метод отправки, вызванный и после применения действия | Имя действия | (...) Аргументы, переданные в действие |
| получение | Getter называется | Getter name | Ценность Getter |
| плагин | Плагин добавлен | Плагин добавлен | (...) Параметры, передаваемые в плагин |
| Registermodule | Зарегистрирован модуль | Пространство имен зарегистрировано | Определение модуля | Магазин, созданный с определением |
| unregistermodule | Модуль незарегистрирован | Пространство имен незарегистрировано | Магазин, созданный с определением |
Как и Vuex, Dragonbinder позволяет разделить ваш магазин на модули, и каждый модуль может содержать собственное определение магазина, включая более вложенные модули.
const moduleA = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... }
}
const moduleB = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... }
modules : {
a : moduleA
}
}
const store = new Dragonbinder ( {
modules : {
b : moduleB
}
} ) ;
console . log ( store . state . b ) // -> `moduleB`'s state
console . log ( store . state [ 'b.a' ] ) // -> `moduleA`'s state Кроме того, после создания магазина вы можете зарегистрировать/нерегистратные модули с помощью методов registerModule и unregisterModule .
Учтите, что когда вы не регистрируете модуль, с ним будут незарегистрированы только его первоначальные вложенные модули.
const moduleA = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... }
}
const moduleB = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... } ,
modules : {
a : moduleA
}
}
const moduleC = {
state : { ... } ,
mutations : { ... } ,
actions : { ... } ,
getters : { ... }
}
const store = new Dragonbinder ( ) ;
store . registerModule ( 'b' , moduleB ) ;
store . registerModule ( 'b.c' , moduleC ) ;
console . log ( store . state . b ) // -> `moduleB`'s state
console . log ( store . state [ 'b.a' ] ) // -> `moduleA`'s state
console . log ( store . state [ 'b.c' ] ) // -> `moduleC`'s state
store . unregisterModule ( 'b' ) ;
console . log ( store . state . b ) // -> undefined
console . log ( store . state [ 'b.a' ] ) // -> undefined
console . log ( store . state [ 'b.c' ] ) // -> `moduleC`'s state Каждый модуль будет вести себя как любой другой магазин, но, в отличие от Vuex, все модули Dragonbinder находятся на именах по дизайну. Нет возможности добавить корневые мутации, действия или добычи с модулем. Таким образом, когда вы называете модульную мутацию, действие или Getter, вам нужно предоставить его полное пространство имен.
Первым аргументом для мутаций и геттеров будет продолжать оставаться местным государством, и с действиями первым аргументом будет локальный контекст/магазин.
Getters получит корневое состояние и корневые добычи в качестве третьего и четвертого аргумента.
Действия будут получить доступ к корневому контексту с помощью свойства rootStore локального контекста.
const moduleA = {
state : {
hello : 'world'
} ,
mutations : {
sayHello ( state , payload ) {
state . hello = payload ;
}
} ,
actions : {
change ( store , payload ) {
store . commit ( 'sayHello' , payload ) ;
store . rootStore . commit ( 'increment' ) ;
}
} ,
getters : {
hello ( state , getters , rootState , rootGetters ) {
return `You have said hello ${ rootState . count } times to ${ state . hello } ` ;
}
}
} ;
const store = new Dragonbinder ( {
state : {
count : 0
} ,
mutations : {
increment ( state ) {
state . count ++ ;
}
} ,
modules : {
a : moduleA
}
} ) ;
store . dispatch ( 'a.change' , 'John Doe' ) ;
console . log ( store . getters [ 'a.hello' ] ) ; // -> You have said hello 1 times to John Doe
console . log ( store . state . count ) // -> 1
console . log ( store . state . a . hello ) // -> John DoeDragonbinder поставляется с простой, но мощной системой плагина. Вы можете расширить его основную функциональность или полностью изменить ее, используя плагины.
let store = new Dragonbinder ( ) ;
store . use ( myPlugin , ... options ) ; Плагин Dragonbinder - это модуль, который экспортирует одну функцию, которая будет вызвана с помощью экземпляра магазина в качестве первого аргумента и, необязательно, с вариантами передаваемых, если таковые имеются.
const Dragonbinder = require ( 'dragonbinder' ) ;
const myPlugin = ( store , ... options ) => {
Dragonbinder . myGlobalMethod = function ( ) {
// Awesome code here
} ;
Dragonbinder . fn . myPrototypeMethod = function ( ) {
// Awesome code here
} ;
store . myLocalMethod = function ( ) {
// Awesome code here
} ;
} ; Проверьте документы по адресу: https://masquerade-circus.github.io/dragonbinder/?api
Проверьте руководство по внесению по адресу: https://masquerade-circus.github.io/dragonbinder/?content=contributing
yarn dev , чтобы посмотреть и компилировать библиотеку при каждом изменении.yarn build , чтобы построить библиотеку.yarn test , чтобы запустить тесты только один раз.yarn dev:test , чтобы запустить тесты, наблюдая за изменениями в библиотеке и тестах.yarn dev:test:nyc чтобы запустить тесты, наблюдая за изменениями, и наконец получить тестовый охват.yarn docs , чтобы создать документацию.yarn docs:watch , чтобы посмотреть и перестроить документацию по каждому изменению в библиотеке или файлах MD.yarn docs:serve , чтобы увидеть сгенерированную документацию на локальном уровне. Автор: Маскарад Цирк. Лицензия Apache-2.0