1KB渐进状态管理库受VUEX启发。
您可以通过NPM注册表提供该库作为Node.js模块:
// 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属性的初始状态,则龙鸟将创建一个。
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根据状态创建计算的属性。这个getters将作为第一个参数和所有其他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 | 添加了活动听众 | 事件名称|听众添加了 |
| 删除者 | 活动听众被删除 | 事件名称|听众删除了 |
| 放 | 添加或修改了状态的属性,在注册模块时也会触发 | 属性名称|新值|旧价值 |
| 删除 | 删除了状态的属性,当模块未注册时也会触发 | 属性名称|旧价值 |
| BeforeCommit | 提交方法调用,并在应用突变之前 | 突变名称| (...)论点传递给突变 |
| 犯罪 | 调用提交方法,并在应用突变之后 | 突变名称| (...)论点传递给突变 |
| BeforedisPatch | 调用方法,并在采用该操作之前 | 动作名称| (...)论点传递给了行动 |
| 派遣 | 调用派遣方法,并在采取操作后 | 动作名称| (...)论点传递给了行动 |
| Getter | 一个被称为 | Getter名称| getter的价值 |
| 插件 | 添加了插件 | 添加了插件| (...)选项传递给插件 |
| 寄存器模块 | 已注册一个模块 | 名称空间注册|模块定义|用定义创建的存储 |
| 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方法进行注册/Unregister模块。
考虑到,当您取消一个模块时,只有其初始嵌套模块不会对其进行注册。
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模块都是由设计命名的。没有选项可以使用模块添加根突变,动作或letters。因此,当您调用模块突变,操作或Getter时,您需要提供其全名空间。
关于突变和Getters的第一个论点将继续是本地状态,而采取行动将是本地上下文/商店。
Getters将获得根状态和根get子作为第三和第四参数。
操作将通过本地上下文的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