สวัสดี ฉันชอบแนวคิดของ vuex และมีร้านค้าระดับโลก แต่ฉันเกลียดการใช้การกลายพันธุ์โดยส่ง magic-string
ไปยังฟังก์ชัน commit เสมอ วิธีแก้ปัญหานี้แค่ขอให้พิมพ์ผิด ดังนั้น เมื่อ typescript ได้รับความนิยม ฉันตื่นเต้นมากที่อาจมีคนแก้ไขการกลายพันธุ์ของ Vuex ดังนั้นคุณไม่จำเป็นต้องใช้ magic-strings
แต่น่าเสียดายที่มันไม่ได้เกิดขึ้น :/
ฉันตัดสินใจตั้งเป้าหมายที่จะสร้างบริการร้านค้าด้วยการดำเนินการที่อิงจากการกลายพันธุ์ที่พิมพ์โดยสมบูรณ์ ดังนั้นฉันจึงสร้างโมดูล vuex ธรรมดาที่มีลักษณะดังนี้:
export const ClientStoreModule = { namespaced: false, state: new ClientStoreState(), getters: { clients(state: ClientStoreState) { return state.Clients; }, }, mutations: { setClients(state: ClientStoreState, clients: Array<Client>) { state.Clients = clients; }, addClient(state: ClientStoreState, client: Client) { state.Clients.push(client); }, }, };
และนี่คือชั้นเรียนของรัฐของฉัน:
export class ClientStoreState { Clients: Array<Client> = []; }
เป้าหมายของฉันคือการบรรลุการกลายพันธุ์ที่สามารถใช้ได้ไม่มากก็น้อยเช่นนี้:
commit<Client>(ClientStoreModule.mutations.addClient, client);
ดังนั้นฉันจึงเริ่มต้นจากปัญหานี้ใน Google และฉันพบห้องสมุดที่ดีชื่อ vuex-typescript
และนี่คือลิงค์:
ไลบรารี่นี้เจ๋ง แต่มันบังคับให้คุณใช้คอมมิตเช่นนี้:
let storeApi = getStoreAccessors<ClientStoreState, RootState>('') let commit = storeApi.commit(ClientStoreModule.mutations.addClient) commit(this.$store, client)
หากต้องการดูเอกสารฉบับเต็ม โปรดไปที่ลิงก์ที่ฉันใส่ไว้ด้านบน
และขอย้ำอีกครั้งว่าเจ๋งกว่าแบบเก่า commit('addClient', client)
ตอนนี้เราได้พิมพ์การกลายพันธุ์ของเราเรียบร้อยแล้ว! แต่วิธีแก้ปัญหานี้ใช้เวลานานและต้องใช้โค้ดจำนวนมากจึงจะใช้งานได้ ฉันก็เลยห่อมันไว้นิดหน่อย
ฉันสร้างคลาสนามธรรมเพื่อขยายบริการในอนาคตของฉันด้วยการดำเนินการ vuex:
import {getStoreAccessors, MutationHandlerWithPayload} from 'vuex-typescript'; export default abstract class BaseStoreService<T> { protected mutations!: Record<string,(state: T, payload: any) => void>; protected storeApi = getStoreAccessors<T, RootState>(''); protected commit<TPayload>(handler: (MutationHandlerWithPayload<T, TPayload>), payload: TPayload) { this.storeApi.commit(handler)(store, payload); } }
ฉันใช้โมดูล vuex ดังนั้น RootState ของฉันจึงเป็นเพียงอินเทอร์เฟซของร้านค้า vuex ทั้งหมดของฉัน
ตกลง ตอนนี้ถึงเวลาสร้างบริการ vuex ในฝันของฉันที่จัดการการกระทำ:
class ClientStore extends BaseStoreService<ClientStoreState> { public mutations = ClientStoreModule.mutations; async addClient(newClient: Client) { this.commit<Client>(this.mutations.addClient, newClient); } async fetchClients(clients) { this.commit(this.mutations.setClients, clients); } } export default new ClientStore();
และตอนนี้เราไปได้แล้ว เราสามารถใช้บริการที่พิมพ์เต็มของเราด้วยการกลายพันธุ์ที่พิมพ์เต็มเช่นนี้ ClientStore.addClient(client)
และรับการเติมโค้ดที่ยอดเยี่ยมของ typescript ทุกที่โดยไม่ต้องใช้ magic-strings
ที่ใดก็ได้
ตกลง ดังนั้นเราจึงจัดการกับการกลายพันธุ์ของเราด้วยวิธีที่ดี แต่แล้ว getters
ล่ะ?
คอมโพเนนต์ Class Bassed Vue ที่เขียนด้วย typescript บังคับให้คุณใช้ไวยากรณ์นี้:
@Getter clients!: Array<Client>;
และอีกครั้งก็ไม่ได้แย่นัก แต่สมมติว่าคุณต้องการฟอร์แมตตัวแปรไคลเอนต์ของคุณใหม่ คุณต้องจำไว้ว่าต้องเปลี่ยนชื่อเหล่านี้ทุกที่และมันก็ยุ่งมาก
กลับไปที่ห้องสมุด vuex-typescript
ของเรากัน เช่นเดียวกับ commit
it ที่มีฟังก์ชัน read
ดังนั้นฉันจึงขยาย BaseStoreService
ของฉันด้วยฟังก์ชันที่สอง:
import {getStoreAccessors, GetterHandler, MutationHandlerNoPayload, MutationHandlerWithPayload} from 'vuex-typescript'; export default abstract class BaseStoreService<T> { protected mutations!: Record<string,(state: T, payload: any) => void>; protected storeApi = getStoreAccessors<T, RootState>(''); protected commit<TPayload>(handler: (MutationHandlerWithPayload<T, TPayload>), payload: TPayload) { this.storeApi.commit(handler)(store, payload); } protected read<TResult>(handler: GetterHandler<T, RootState, TResult>): TResult { return this.storeApi.read<TResult>(handler)(store); } }
ตอนนี้ฉันสามารถเพิ่ม ClientStore
service typescript getter ของฉันด้วยการสนับสนุน typescript แบบเต็มและเขียน getter ที่พิมพ์เต็มของฉันดังนี้:
get getClients() { return this.read<Array<Client>>(ClientStoreModule.getters.clients) }
เพียงเท่านี้ เรามี getters ที่พิมพ์เต็มและการกลายพันธุ์ที่พิมพ์เต็มในบริการ ClientStore
ของเรา และเราสามารถเข้าถึง vuex getters ของเราได้ดังนี้:ClientStore.getClients()