tab.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import {createStore} from 'zustand/vanilla';
  2. type State = {
  3. activeKey: string;
  4. tabList: {
  5. key: string;
  6. url: string;
  7. label: string;
  8. }[];
  9. };
  10. type DispatchOptions =
  11. | {type: 'ADD'; payload: State['tabList'][0]}
  12. | {type: 'REMOVE'; payload: string}
  13. | {type: 'REMOVE_OTHER'; payload: string}
  14. | {type: 'REMOVE_RIGHT'; payload: string}
  15. | {type: 'CLEAR'}
  16. | {type: 'SORT'; payload: State['tabList']};
  17. type Action = {
  18. setActiveKey: (key: string | ((prev: string) => string)) => void;
  19. dispatch: (value: DispatchOptions) => void;
  20. };
  21. const defaultTab: State['tabList'][0] = {
  22. key: '-1',
  23. url: '/main',
  24. label: '首页',
  25. };
  26. function reducer(
  27. state: State['tabList'],
  28. action: DispatchOptions,
  29. ): State['tabList'] {
  30. const {type} = action;
  31. switch (type) {
  32. case 'ADD': {
  33. const {payload} = action;
  34. const exist = state.find(val => val.key === payload.key);
  35. if (exist) {
  36. return state;
  37. }
  38. return [...state, payload];
  39. }
  40. case 'REMOVE': {
  41. const {payload} = action;
  42. const idx = state.findIndex(val => val.key === payload);
  43. if (idx < 0) return state;
  44. const nextState = [...state];
  45. nextState.splice(idx, 1);
  46. return nextState;
  47. }
  48. case 'REMOVE_OTHER': {
  49. const {payload} = action;
  50. const idx = state.findIndex(val => val.key === payload);
  51. if (idx < 0) return state;
  52. return [{...defaultTab}, {...state[idx]}];
  53. }
  54. case 'REMOVE_RIGHT': {
  55. const {payload} = action;
  56. const idx = state.findIndex(val => val.key === payload);
  57. if (idx < 0) return state;
  58. const {length} = state;
  59. const nextState = [...state];
  60. nextState.splice(idx + 1, length - idx - 1);
  61. return nextState;
  62. }
  63. case 'CLEAR': {
  64. return [{...defaultTab}];
  65. }
  66. case 'SORT':
  67. return action.payload;
  68. default:
  69. return state;
  70. }
  71. }
  72. export const tabStore = createStore<State & Action>(function (set) {
  73. return {
  74. activeKey: '-1',
  75. tabList: [defaultTab],
  76. setActiveKey(key) {
  77. set(function (prev) {
  78. return {activeKey: typeof key === 'string' ? key : key(prev.activeKey)};
  79. });
  80. },
  81. dispatch(value) {
  82. set(function (prev) {
  83. let nextActiveKey = prev.activeKey;
  84. const result = reducer(prev.tabList, value);
  85. switch (value.type) {
  86. case 'ADD':
  87. nextActiveKey = value.payload.key;
  88. break;
  89. case 'REMOVE': {
  90. const idx = prev.tabList.findIndex(
  91. val => val.key === value.payload,
  92. );
  93. idx >= 0 && (nextActiveKey = prev.tabList[idx].key);
  94. break;
  95. }
  96. case 'REMOVE_OTHER':
  97. nextActiveKey = value.payload;
  98. break;
  99. case 'REMOVE_RIGHT': {
  100. result.findIndex(val => val.key === prev.activeKey) < 0 &&
  101. (nextActiveKey = value.payload);
  102. break;
  103. }
  104. case 'CLEAR':
  105. nextActiveKey = '-1';
  106. break;
  107. case 'SORT': {
  108. break;
  109. }
  110. }
  111. return {tabList: result, activeKey: nextActiveKey};
  112. });
  113. },
  114. };
  115. });