1KB Progressive State Management Library ซึ่งได้รับแรงบันดาลใจจาก 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' ) ;นอกจากนี้หากคุณต้องการหลีกเลี่ยง Singletons เพื่อนำคำจำกัดความของร้านค้ามาใช้ซ้ำคุณสามารถประกาศสถานะเป็นฟังก์ชั่นจากโรงงาน
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' ) ;หากคุณต้องการจัดการฟังก์ชั่น async คุณต้องใช้การกระทำ และการกระทำจะส่งคืนสัญญาเสมอเนื่องจากการเรียกพวกเขา
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
พิจารณาว่าเมื่อคุณยกเลิกการลงทะเบียนโมดูลจะมีเพียงโมดูลซ้อนเริ่มต้นเท่านั้นที่จะไม่ได้ลงทะเบียนกับมัน
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 ทั้งหมดจะถูกกำหนดโดยการออกแบบ ไม่มีตัวเลือกในการเพิ่มการกลายพันธุ์รูทการกระทำหรือ getters ด้วยโมดูล ดังนั้นเมื่อคุณเรียกการกลายพันธุ์ของโมดูลการกระทำหรือ getter คุณต้องจัดหาเนมสเปซแบบเต็ม
อาร์กิวเมนต์แรกสำหรับการกลายพันธุ์และ getters จะยังคงเป็นสถานะท้องถิ่นและด้วยการกระทำอาร์กิวเมนต์แรกจะเป็นบริบท/ร้านค้าในท้องถิ่น
Getters จะได้รับสถานะรูทและรูท 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 เพื่อดูและสร้างเอกสารเกี่ยวกับการเปลี่ยนแปลงทุกครั้งในไลบรารีหรือไฟล์ MDyarn docs:serve เพื่อดูเอกสารที่สร้างขึ้นในพื้นที่ ผู้แต่ง: Masquerade Circus ใบอนุญาต apache-2.0