|
|
@@ -0,0 +1,141 @@
|
|
|
+
|
|
|
+import {createStore} from 'zustand/vanilla';
|
|
|
+
|
|
|
+type State = {
|
|
|
+ activeKey: string;
|
|
|
+ tabList: {
|
|
|
+ key: string;
|
|
|
+ url: string;
|
|
|
+ label: string;
|
|
|
+ }[];
|
|
|
+};
|
|
|
+type DispatchOptions =
|
|
|
+ | {type: 'ADD'; payload: State['tabList'][0]}
|
|
|
+ | {type: 'REMOVE'; payload: string}
|
|
|
+ | {type: 'REMOVE_OTHER'; payload: string}
|
|
|
+ | {type: 'REMOVE_RIGHT'; payload: string}
|
|
|
+ | {type: 'CLEAR'}
|
|
|
+ | {type: 'SORT'; payload: State['tabList']};
|
|
|
+
|
|
|
+type Action = {
|
|
|
+ setActiveKey: (key: string | ((prev: string) => string)) => void;
|
|
|
+ dispatch: (value: DispatchOptions) => void;
|
|
|
+ clear: () => void;
|
|
|
+};
|
|
|
+
|
|
|
+const defaultTab: State['tabList'][0] = {
|
|
|
+ key: '-1',
|
|
|
+ url: '/main',
|
|
|
+ label: '首页',
|
|
|
+};
|
|
|
+
|
|
|
+function reducer(
|
|
|
+ state: State['tabList'],
|
|
|
+ action: DispatchOptions,
|
|
|
+): State['tabList'] {
|
|
|
+ const {type} = action;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case 'ADD': {
|
|
|
+ const {payload} = action;
|
|
|
+
|
|
|
+ const exist = state.find(val => val.key === payload.key);
|
|
|
+ if (exist)
|
|
|
+ return state;
|
|
|
+
|
|
|
+ return [...state, payload];
|
|
|
+ }
|
|
|
+ case 'REMOVE': {
|
|
|
+ const {payload} = action;
|
|
|
+ const idx = state.findIndex(val => val.key === payload);
|
|
|
+ if (idx < 0)
|
|
|
+ return state;
|
|
|
+
|
|
|
+ const nextState = [...state];
|
|
|
+ nextState.splice(idx, 1);
|
|
|
+ return nextState;
|
|
|
+ }
|
|
|
+ case 'REMOVE_OTHER': {
|
|
|
+ const {payload} = action;
|
|
|
+ const idx = state.findIndex(val => val.key === payload);
|
|
|
+ if (idx < 0)
|
|
|
+ return state;
|
|
|
+
|
|
|
+ return [{...defaultTab}, {...state[idx]}];
|
|
|
+ }
|
|
|
+ case 'REMOVE_RIGHT': {
|
|
|
+ const {payload} = action;
|
|
|
+ const idx = state.findIndex(val => val.key === payload);
|
|
|
+ if (idx < 0)
|
|
|
+ return state;
|
|
|
+
|
|
|
+ const {length} = state;
|
|
|
+ const nextState = [...state];
|
|
|
+ nextState.splice(idx + 1, length - idx - 1);
|
|
|
+
|
|
|
+ return nextState;
|
|
|
+ }
|
|
|
+ case 'CLEAR': {
|
|
|
+ return [{...defaultTab}];
|
|
|
+ }
|
|
|
+ case 'SORT':
|
|
|
+ return action.payload;
|
|
|
+ default:
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const tabStore = createStore<State & Action>(function(set) {
|
|
|
+ return {
|
|
|
+ activeKey: '',
|
|
|
+ tabList: [],
|
|
|
+ setActiveKey(key) {
|
|
|
+ set(function(prev) {
|
|
|
+ return {activeKey: typeof key === 'string' ? key : key(prev.activeKey)};
|
|
|
+ });
|
|
|
+ },
|
|
|
+ dispatch(value) {
|
|
|
+ set(function(prev) {
|
|
|
+ let nextActiveKey = prev.activeKey;
|
|
|
+ const result = reducer(prev.tabList, value);
|
|
|
+
|
|
|
+ switch (value.type) {
|
|
|
+ case 'ADD': // 新增后key改为最后一个
|
|
|
+ nextActiveKey = value.payload.key;
|
|
|
+ break;
|
|
|
+ case 'REMOVE': {
|
|
|
+ // 如果关闭的是当前active 修改为active的前一个
|
|
|
+ const idx = prev.tabList.findIndex(
|
|
|
+ val => val.key === value.payload,
|
|
|
+ );
|
|
|
+
|
|
|
+ prev.activeKey === prev.tabList[idx].key
|
|
|
+ && (nextActiveKey = prev.tabList[idx - 1].key);
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 'REMOVE_OTHER': // 修改为关闭的那个
|
|
|
+ nextActiveKey = value.payload;
|
|
|
+ break;
|
|
|
+ case 'REMOVE_RIGHT': {
|
|
|
+ // 判断是否关闭了active 如果关闭了则显示触发的那个
|
|
|
+ result.findIndex(val => val.key === prev.activeKey) < 0
|
|
|
+ && (nextActiveKey = value.payload);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 'CLEAR': // 显示首页
|
|
|
+ nextActiveKey = '-1';
|
|
|
+ break;
|
|
|
+ case 'SORT':
|
|
|
+ // 不需要操作
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return {tabList: result, activeKey: nextActiveKey};
|
|
|
+ });
|
|
|
+ },
|
|
|
+ clear() {
|
|
|
+ set({activeKey: '-1', tabList: []});
|
|
|
+ },
|
|
|
+ };
|
|
|
+});
|