Biblioteca de Gerenciamento de Estado Progressivo de 1KB inspirado pela Vuex.
Você pode obter esta biblioteca como um módulo Node.js disponível no Registro da NPM:
// With npm
$ npm install dragonbinder
// With yarn
$ yarn add dragonbinder Ou você pode usá -lo independente no navegador com: <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 ) // -> 1O DragonBinder usa proxies para criar um estado como uma "fonte única de verdade" que não pode ser alterada, a menos que você cometa uma mutação. Isso significa que você não pode excluir, modificar ou adicionar uma propriedade diretamente. Isso nos permite acompanhar todas as mudanças que fizemos no estado.
Se você não fornecer um estado inicial pelo Dragonbinder da propriedade state , criará um.
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' ) ;Além disso, se você deseja evitar singletons para reutilizar a definição inicial da loja, poderá declarar seu estado como uma função de fábrica.
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 ) ; // -> 4Assim como Vue, com o DragonBinder, você pode criar getters para criar propriedades computadas com base no estado. Esses getters receberão o estado como primeiro argumento e todos os outros getters como segundo.
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 ) ; // -> 1Mutações são a única maneira de mudar o estado e você deve considerar os próximos pontos ao projetar mutações.
Object.freeze para evitar alterações diretas. Portanto, quando você está alterando o estado usando uma mutação, pode adicionar, modificar ou excluir apenas propriedades de primeiro nível, as propriedades de segundo nível serão apenas leituras. 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' ) ;Se você precisar lidar com funções assíncronas, deve usar ações. E as ações sempre retornarão uma promessa como resultado de chamá -las.
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 secondVocê pode se registrar/não registrar retornos de chamada em eventos.
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' ) ; Todos os eventos recebem a instância da loja como o primeiro argumento.
| Nome do evento | É chamado quando | Argumentos recebidos por local |
|---|---|---|
| addListener | Um ouvinte de evento é adicionado | Nome do evento | Ouvinte adicionado |
| Removelistener | Um ouvinte de evento é removido | Nome do evento | Ouvinte removido |
| definir | Uma propriedade do estado é adicionada ou modificada, também acionada quando um módulo é registrado | Nome da propriedade | Novo valor | Valor antigo |
| excluir | Uma propriedade do estado é excluída, também acionada quando um módulo não é registrado | Nome da propriedade | Valor antigo |
| beforeComit | Método de comprometimento chamado e antes de aplicar a mutação | Nome da mutação | (...) argumentos passados para a mutação |
| comprometer-se | Método de comprometimento chamado e após aplicar a mutação | Nome da mutação | (...) argumentos passados para a mutação |
| beforedispatch | Método de expedição chamado e antes de aplicar a ação | Nome da ação | (...) argumentos passados para a ação |
| expedição | Método de expedição chamado e após aplicar a ação | Nome da ação | (...) argumentos passados para a ação |
| getter | Um getter é chamado | Nome do getter | Valor do getter |
| plugin | Um plugin é adicionado | Plug -in adicionado | (...) Opções passadas para o plug -in |
| RegisterModule | Um módulo está registrado | Namespace registrado | Definição do módulo | Loja criada com a definição |
| UNLOGISTERMODULE | Um módulo não é registrado | Espaço para nome não registrado | Loja criada com a definição |
Como a Vuex, o DragonBinder permite dividir sua loja em módulos e cada módulo pode conter sua própria definição de loja, incluindo mais módulos aninhados.
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 Além disso, depois que a loja for criada, você pode registrar/não registrar módulos com os métodos registerModule e unregisterModule .
Considere que, quando você não registrar um módulo, apenas seus módulos aninhados iniciais não serão registrados com ele.
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 Cada módulo se comportará como qualquer outra loja, mas, diferentemente da Vuex, todos os módulos DragonBinder são nomes de design. Não há opção para adicionar mutações, ações ou getters raiz com um módulo. Portanto, quando você chama uma mutação, ação ou getter do módulo, precisa fornecer seu espaço de nome completo.
O primeiro argumento para mutações e getters continuará sendo o estado local e, com ações, o primeiro argumento será o contexto/loja local.
Os getters receberão o estado raiz e os getters de raiz como o terceiro e o quarto argumentos.
As ações acessarão o contexto raiz pela propriedade rootStore do contexto local.
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 DoeO DragonBinder vem com um sistema de plug -in simples, mas poderoso. Você pode estender sua funcionalidade principal ou alterá -la completamente usando plugins.
let store = new Dragonbinder ( ) ;
store . use ( myPlugin , ... options ) ; Um plug -in DragonBinder é um módulo que exporta uma única função que será chamada na instância da loja como primeiro argumento e, opcionalmente, com as opções aprovadas, se houver.
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
} ;
} ; Verifique os documentos em: https://masquerade-circus.github.io/dragonbinder/?api
Verifique o guia contribuinte em: https://masquerade-circus.github.io/dragonbinder/?content=contribution
yarn dev para assistir e compilar a biblioteca em todas as alterações.yarn build para construir a biblioteca.yarn test para executar testes apenas uma vez.yarn dev:test para executar os testes assistindo alterações na biblioteca e nos testes.yarn dev:test:nyc para executar os testes assistindo alterações e obter a cobertura do teste finalmente.yarn docs para construir a documentação.yarn docs:watch para assistir e reconstruir a documentação sobre todas as alterações na biblioteca ou nos arquivos MD.yarn docs:serve para ver a documentação gerada localmente. Autor: Misfar Circus. Licença Apache-2.0