store/src/store.ts
2024-12-01 23:58:08 +08:00

109 lines
2.8 KiB
TypeScript

import { createStore as createZutandStore, StateCreator, StoreApi } from 'zustand/vanilla';
import { shallow } from 'zustand/shallow';
import { get } from 'lodash-es';
import deepEqual from 'fast-deep-equal';
export const create = createZutandStore;
export type { StateCreator, StoreApi };
type Listener = (state: any, prevState: any) => void;
export class StoreManager {
stores: Record<string, any>;
constructor() {
this.stores = {};
}
createStore<T = any, U extends T = any>(initialStore: StateCreator<T, [], [], U>, key: string) {
if (this.stores[key]) {
return this.stores[key];
}
this.stores[key] = createZutandStore(initialStore);
return this.stores[key] as StoreApi<T>;
}
create<T = any, U extends T = any>(initialStore: StateCreator<T, [], [], U>, key: string) {
return this.createStore(initialStore, key);
}
getStore(key: string) {
return this.stores[key];
}
removeStore(key: string) {
delete this.stores[key];
}
clearStores() {
this.stores = {};
}
shallow(objA: any, objB: any) {
return shallow(objA, objB);
}
/**
* path 为可以是 '.a.b.c'的形式
* @param fn
* @param param1
* @returns
*/
subscribe(fn: Listener, { key, path, deep, store }: { key: string; path: string; deep?: boolean; store?: StoreApi<any> }) {
const _store = store || (this.stores[key] as StoreApi<any>);
if (!_store) {
console.error('no store', key);
return;
}
return _store.subscribe((newState, oldState) => {
try {
const newPath = get(newState, path);
const oldPath = get(oldState, path);
if (!newPath && !oldPath) {
return;
}
if (deep) {
if (!deepEqual(newPath, oldPath)) {
fn?.(newState, oldState);
}
return;
}
if (!shallow(newPath, oldPath)) {
fn?.(newState, oldState);
}
} catch (e) {
console.error('subscribe error', e);
}
});
}
}
// export const store = new StoreManager();
type FnListener<T = any> = (state: T, prevState: T) => void;
type SubOptions = {
path?: string;
deep?: boolean;
store?: StoreApi<any>;
};
export const sub = <T = any>(fn: FnListener<T>, { path, deep, store }: SubOptions) => {
if (!store) {
console.error('no store');
return;
}
return store.subscribe((newState: T, oldState: T) => {
try {
const newPath = get(newState, path);
const oldPath = get(oldState, path);
if (!newPath && !oldPath) {
// 都不存在
return;
}
if (deep) {
if (!deepEqual(newPath, oldPath)) {
fn?.(newState, oldState);
}
return;
}
if (!shallow(newPath, oldPath)) {
fn?.(newState, oldState);
}
} catch (e) {
console.error('subscribe error', e);
}
});
};
export { shallow, deepEqual };