forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.2 KiB
7.2 KiB
Store
Vuex-like state management pattern with Actions, Getters, Mutations, and State classes.
Overview
The store implements a Vuex-like pattern using separate classes for State, Actions, Getters, and Mutations. It uses Vuex's createStore function.
Architecture
Store
├── State (reactive data)
├── Actions (async operations that commit mutations)
├── Mutations (synchronous state changes)
└── Getters (computed values)
State Class
File: /home/hechang27/Documents/sprt/noob-components/plugs/store/index.ts
export class State {
dict = {
active_status: {
A: "启用",
B: "禁用",
},
};
roles = {};
menus = [];
roleRefresh = true;
style = Styles.plain;
size = Size.normal;
actions = [];
user = {};
actionPers = {};
refreshFlags = new Map();
}
State Properties
| Property | Type | Description |
|---|---|---|
dict |
object | Dictionary mappings by code |
roles |
object | Role ID to name mapping |
menus |
array | User menu permissions |
roleRefresh |
boolean | Flag to trigger role refresh |
style |
Styles.plain | Current theme style |
size |
Size.normal | Current size variant |
actions |
array | User action permissions |
user |
object | Current user object |
actionPers |
object | Action permission mappings |
refreshFlags |
Map | Refresh flag tokens per flag name |
Actions Class
File: /home/hechang27/Documents/sprt/noob-components/plugs/store/index.ts
export class Actions {
getDictMap = ({ state, commit }, codes) => {
if (codes == null) {
return;
}
const arr: Array<any> = [];
for (let i = 0; i < codes.length; i++) {
const code = codes[i];
state.dict[code] || arr.push(code);
}
if (arr.length == 0) {
return;
}
getByCodes({ codes: arr.join() }).then((rsp: any) => {
if (rsp) {
for (let i = 0; i < arr.length; i++) {
const key = arr[i];
const dict = {};
if (rsp[key]) {
rsp[key].forEach((item) => {
dict[item.code] = item.name;
});
}
commit("updateDict", [key, dict]);
}
}
});
};
getRoleMap = ({ state, commit }) => {
state.roleRefresh &&
mapping().then((rsp) => {
commit("updateState", ["roles", rsp]);
commit("updateState", ["roleRefresh", false]);
});
};
getMenus = ({ state, commit }) => {
getMenus().then((rsp) => commit("updateState", ["menus", rsp]));
};
getMyActions = ({ state, commit }, content) => {
getActions(content).then((rsp) => commit("updateState", ["actions", rsp]));
};
login = (store) => {
const { state, commit } = store;
state.size.headHeight = state.size.head + "px";
state.size.asideWidth = state.size.aside + "px";
commit("initSize");
this.getMenus(store);
};
setRefreshFlag = ({ state, commit }, flags: string[]) => {
commit("setRefreshFlag", flags);
};
unsetRefreshFlag = ({ state, commit }, params: { flags: string[]; token: string }) => {
commit("unsetRefreshFlag", params);
};
}
Actions Pattern
- Actions receive Vuex store object with
state,commit,dispatch - Actions call API functions and commit mutations
- Actions never directly modify state
- Actions can call other actions via
dispatch
Key Actions
| Action | Description |
|---|---|
getDictMap |
Fetches dictionary entries by codes, caches in state |
getRoleMap |
Fetches role mappings if refresh is needed |
getMenus |
Fetches user menu permissions |
getMyActions |
Fetches user action permissions |
login |
Initializes size settings and fetches menus |
setRefreshFlag |
Creates empty refresh flag sets |
unsetRefreshFlag |
Adds token to refresh flag sets |
Mutations Class
File: /home/hechang27/Documents/sprt/noob-components/plugs/store/index.ts
export class Mutations {
updateState = (state, [k, v]) => {
state[k] = v;
};
initSize = (state, param) => {
const size = state.size;
const aside = parseInt(size.asideWidth);
const head = parseInt(size.headHeight);
const mainPad = parseInt(size.mainPad);
const searchRow = parseInt(size.searchRowHeight);
const searchRowPad = parseInt(size.searchRowPad);
const headRightWidth = parseInt(size.headRightWidth);
if (param) {
size.height = param[0];
size.width = param[1];
}
size.mainHeight = Math.floor(size.height - head) + "px";
size.tableHeight = size.height - 2 * (mainPad + searchRowPad) - 3 - searchRow - head;
size.pTableHeight = size.tableHeight - size.pageHeight;
size.headLeftWidth = size.width - aside - headRightWidth - 20 + "px";
};
updateDict = (state, param) => {
state.dict[param[0]] = param[1];
};
setRefreshFlag = (state, flags: string[]) => {
for (const flag of flags) {
state.refreshFlags.set(flag, new Set());
}
};
unsetRefreshFlag = (state, { flags, token }: { flags: string[]; token: string }) => {
for (const flag of flags) {
if (!state.refreshFlags.has(flag)) {
state.refreshFlags.set(flag, new Set());
}
state.refreshFlags.get(flag).add(token);
}
};
}
Mutations Pattern
- Mutations receive
statedirectly - Mutations are synchronous
- Mutations use array destructuring for multiple parameters:
([k, v]) - Mutations directly modify state properties
Key Mutations
| Mutation | Description |
|---|---|
updateState |
Generic state update: commit("updateState", ["key", value]) |
initSize |
Initializes size-dependent calculated values |
updateDict |
Updates dictionary entry: commit("updateDict", [code, mapping]) |
setRefreshFlag |
Creates new refresh flag with empty Set |
unsetRefreshFlag |
Adds token to refresh flag Set |
Getters Class
File: /home/hechang27/Documents/sprt/noob-components/plugs/store/index.ts
export class Getters {
menuIconSize = (state) => {
return state.size.menuIconSize;
};
}
Getters Pattern
- Getters receive
stateas first parameter - Getters compute and return derived values
- Getters are cached based on dependencies
Store Creation
export interface StoreOptions {
state?: State;
getters?: Getters;
actions?;
mutations?: Mutations;
modules?;
plugins?;
strict?: boolean;
devtools?: boolean;
}
export const createStore = (options) => {
return create(options);
};
Usage in Component
import { createStore } from "vuex";
import { State, Actions, Mutations, Getters } from "./store";
const store = createStore({
state: new State(),
getters: new Getters(),
actions: new Actions(),
mutations: new Mutations(),
strict: true,
});
Anti-Patterns
- Never modify state directly in actions - Always use
committo call mutations - Do not put async logic in mutations - Mutations must be synchronous
- Do not use mutation names as variables - Always use string literals for mutation names
- Do not skip the
initSizemutation - Without it, derived values likemainHeightwill be incorrect
Language: English