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