UNPKG

@nnnb/prompt

Version:

A factory method that supports various modal components in function call. Support asynchronous collection and function call.

104 lines (84 loc) 2.79 kB
// 导入深拷贝函数 import cloneDeep from "lodash/cloneDeep"; // 导入 useSyncExternalStore 的导出 import useSyncExternalStoreExports from "use-sync-external-store/shim"; // 获取 useSyncExternalStore const { useSyncExternalStore } = useSyncExternalStoreExports; // 定义监听器类型 type Listener = () => void; // 定义 Store 的基础接口 interface StoreInterface<T = any> { state: T; restore: T; listeners: Set<Listener>; dispatch: (payload: Partial<T>) => void; subscribe: (listener: Listener) => () => void; getSnapshot: () => T; use: () => T; } class Store<T extends object> implements StoreInterface<T> { public state: T; public restore: T; public listeners: Set<Listener>; constructor(initialState: T) { this.state = initialState; this.restore = cloneDeep(initialState); this.listeners = new Set(); } private get listenerCount(): number { return this.listeners.size; } public dispatch = (payload: Partial<T>): void => { this.state = { ...this.state, ...payload }; this.notifyListeners(); }; private notifyListeners(): void { this.listeners.forEach((listener) => listener()); } public subscribe = (listener: Listener): () => void => { this.listeners.add(listener); return () => { this.listeners.delete(listener); if (this.listenerCount === 0) { this.resetState(); } }; }; private resetState(): void { this.state = cloneDeep(this.restore); } public getSnapshot = (): T => { return this.state; }; public use(): T { return useStore(this); } } export const create = <T extends object>(initialState: T): T & { use: () => T } => { const store = new Store<T>(initialState); const proxy = new Proxy(store, { get(target, prop: string | symbol, receiver): any { if (!["subscribe", "getSnapshot", "use"].includes(prop.toString())) { return target.state[prop as keyof T]; } return Reflect.get(target, prop, receiver); }, set(target, prop: string | symbol, value: any): boolean { if (target.state[prop as keyof T] !== value) { target.dispatch({ [prop as keyof T]: value } as Partial<T>); } return true; } }); return proxy as unknown as T & { use: () => T }; }; const useStore = <T>(store: StoreInterface<T>): T => { const state = useSyncExternalStore(store.subscribe, store.getSnapshot); // 绑定方法的 this 上下文 Object.keys(state).forEach((key) => { if (typeof state[key as keyof T] === "function") { (state[key as keyof T] as Function) = (state[key as keyof T] as Function).bind(store); } }); return state; };