在 Vuex 中,中间件主要通过 插件(Plugins) 和 action 拦截 实现。虽然 Vuex 没有明确的“中间件”概念,但可以通过以下两种方式达到类似效果:
1. 使用 subscribeAction
监听 Action(推荐)
这是 Vuex 官方推荐的方式,通过 store.subscribeAction
监听 action 的执行前后,添加额外逻辑。
示例:日志记录中间件
const logMiddleware = (store) => {
// 监听 action 执行前
store.subscribeAction((action, state) => {
console.log(`[Before] Action: ${
action.type}, Payload: ${
action.payload}`);
});
// 监听 action 执行后(包括异步 action)
store.subscribeAction({
after: (action, state) => {
console.log(`[After] Action: ${
action.type}`);
},
error: (action, error) => {
console.error(`[Error] Action: ${
action.type}, Error: ${
error.message}`);
}
});
};
// 在创建 store 时注册插件
const store = new Vuex.Store({
// ... 其他配置
plugins: [logMiddleware]
});
AI 代码解读
示例:权限验证中间件
const permissionMiddleware = (store) => {
store.subscribeAction((action, state) => {
// 需要权限验证的 action
const protectedActions = ['deleteItem', 'updateUser'];
if (protectedActions.includes(action.type)) {
const user = state.user;
if (!user || !user.isAdmin) {
console.error('Permission denied');
// 阻止 action 继续执行(需结合自定义 dispatch)
throw new Error('Permission denied');
}
}
});
};
AI 代码解读
2. 重写 store.dispatch
方法
通过拦截 dispatch
方法,可以更精细地控制 action 的执行流程。
示例:自定义 dispatch 中间件
const middlewarePlugin = (store) => {
const originalDispatch = store.dispatch;
// 重写 dispatch 方法
store.dispatch = (action) => {
console.log('[Middleware] Before dispatch:', action);
// 添加自定义逻辑(如权限检查、日志记录)
if (action.type === 'sensitiveAction') {
if (!store.state.user.isAdmin) {
console.error('Unauthorized');
return Promise.reject(new Error('Unauthorized'));
}
}
// 执行原始 dispatch
const result = originalDispatch(action);
console.log('[Middleware] After dispatch:', action);
return result;
};
};
// 注册插件
const store = new Vuex.Store({
plugins: [middlewarePlugin]
});
AI 代码解读
3. 处理异步 Action
对于异步 action,subscribeAction
会在 action 开始和结束时分别触发:
store.subscribeAction({
before: (action, state) => {
console.log(`[Async Before] ${
action.type}`);
},
after: (action, state) => {
console.log(`[Async After] ${
action.type}`);
}
});
// 异步 action
actions: {
async fetchData({
commit }) {
commit('SET_LOADING', true);
try {
const response = await fetch('/api/data');
commit('SET_DATA', await response.json());
} finally {
commit('SET_LOADING', false);
}
}
}
AI 代码解读
4. 多个中间件的执行顺序
插件按注册顺序执行,先注册的中间件会先执行:
const middleware1 = (store) => {
/* ... */ };
const middleware2 = (store) => {
/* ... */ };
const store = new Vuex.Store({
plugins: [middleware1, middleware2] // 先执行 middleware1
});
AI 代码解读
5. 注意事项
- 避免副作用:中间件应保持纯粹,避免直接修改 state 或产生其他副作用。
- 性能考虑:过多或复杂的中间件会增加 action 执行的延迟,尤其是在高频触发场景下。
- 与 Vuex 插件区分:中间件主要关注 action 流程,而插件可用于更广泛的场景(如状态持久化)。
总结
Vuex 的中间件通过 插件 + action 监听 实现,核心是利用 subscribeAction
或重写 dispatch
方法。这种方式能在不改变 Vuex 核心逻辑的前提下,灵活添加额外功能(如日志、权限、错误处理)。