在前端应用程序中,数据管理是一个重要的任务,它通常由状态管理库来处理。Redux 和 VueX 都是常见的状态管理库。它们具有相似的原理和使用方法,但是它们的中间件机制略有不同。本文将介绍 Redux 和 VueX 的中间件使用和原理,以及如何实现一个简单的中间件。
Redux 中间件
什么是中间件?
Redux 中间件是一个函数,它可以在 Redux 的 action 和 reducer 之间进行拦截、处理和改变 action 或者副作用(如异步操作)。
例如,Redux 可以通过 middleware 让 dispatch 函数变成一个可以传入的参数。然后中间件可以通过这个 dispatch 函数来监听 action,执行一些操作并且可以发出一个或多个新的 action。这样可以简化复杂的业务逻辑,并且避免在组件中直接进行副作用操作。
Redux 中间件的使用
Redux 中间件的使用分为两种情形:全局和仅限于某个 action。
- 全局中间件
在 Redux 中间件中,最先调用的是最外层的中间件,最后调用的是最里层的中间件。这意味着每个中间件都可以直接访问 action 和所有之前的中间件对它的修改。
例如,下面的日志中间件会在每次 dispatch 时记录下 action 和当前的状态:
const loggingMiddleware = store => next => action => { console.log('dispatching', action, store.getState()) const result = next(action) console.log('next state', store.getState()) return result }
将中间件应用到 Redux 的方式非常简单,只需要使用 applyMiddleware 函数:
import { createStore, applyMiddleware } from 'redux' import rootReducer from '../reducers' import loggingMiddleware from './loggingMiddleware' const store = createStore(rootReducer, applyMiddleware(loggingMiddleware))
在这里,我们只添加了一个中间件,但是也可以添加多个中间件。当 dispatch 一个 action 时,这些中间件会以倒序的方式执行,直到最 Inner 的 reducer。
- 特定 action 的中间件
与应用在全局中的中间件不同,特定 action 的中间件只对指定的 action 进行处理。这对于需要对某些 action 进行优化的场合非常有用。
例如,下面的 Thunk 中间件会将 promise based 的异步操作转换为普通 action:
const thunkMiddleware = store => next => action => { if (typeof action === 'function') { return action(store.dispatch, store.getState) } return next(action) }
要使用这种中间件,只需要在调用 dispatch 时传入一个函数而非正常的 action 即可:
store.dispatch((dispatch, getState) => { dispatch({ type: 'FETCH_START' }) fetch('/api/data') .then(response => response.json()) .then(data => dispatch({ type: 'FETCH_COMPLETE', payload: data })) .catch(error => dispatch({ type: 'FETCH_FAILED', payload: error })) })
Redux 中间件的原理
Redux 中间件的原理非常简单。每个 middleware 都被包装在一个函数内,这个函数和所有其它的中间件一样,都接收了 Store 的 dispatch 和 getState 方法作为参数,然后返回另一个函数,这个函数又接收第二个中间件作为参数。
这个被返回的函数将会对下一个中间件的方法进行调用,或者直接返回 dispatch 或 getState 的结果。这也是为什么每个中间件最后都必须返回一个 action 的原因:否则就无法继续将 action 发入下一个中间件。
Redux 中间件的思路非常好,它将处理的过程拆分成了多个步骤,每个步骤都由单独的一个函数进行处理。所有中间件的顺序决定了数据流的顺序,从而让 Redux 更加灵活和可扩展。
VueX 中间件
什么是中间件?
和 Redux 中间件类似,在 VueX 应用中,中间件是一个函数,它可以在每次 mutation 时对数据状态进行处理或副作用操作。
例如,下面的日志中间件可以在每次 mutation 的时候记录数据变化:
const logger = store => { store.subscribe((mutation, state) => { console.log(mutation.type, mutation.payload, state) }) }
VueX 中间件的使用
在 VueX 中,可以通过插件的方式来添加中间件:
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, plugins: [logger] // 中间件放在 plugins 数组中 })
除了添加全局中间件之外,还可以添加特定模块的中间件。例如,下面的日志中间件只监视 cart 模块的 mutation:
const cartLogger = store => { const cartModule = store._modules.root._children.cart cartModule.forEachMutation((mutation, mutationType) => { console.log(`[Cart] ${mutationType}`) }) }
在 cart 模块中,添加中间件和全局使用相同:
const cartModule = { state: { ... }, mutations: { ... }, plugins: [cartLogger] // 中间件放在 plugins 数组中 }
VueX 中间件的原理
VueX 中间件的原理和 Redux 中间件类似,它们都能够将操作拆分成多个步骤,并且 MongoDB 可以为每个步骤添加额外的副作用。
在 VueX 中,中间件支持全局和特定模块的应用。
中间件就是一个函数,它接收一个 Store 对象作为参数。这个 Store 包含有整个应用内的 state,提供 getters、dispatch、commit 等方法,这些操作会改变 state 对象的状态。
中间件函数可以对 Store 上的属性进行修改,例如监听 Store 上的某一个 特定状态,或者监听 Store 上的提交或者异步操作,也可以连续使用多个中间件。
如何自己实现一个简单的中间件
自己实现一个中间件非常简单,下面的例子说明了如何实现一个简单的计数器中间件:
const middleware = store => next => { let count = 0 return action => { count++ console.log(`The ${count} times middleware called`) next(action) } }
该中间件简单的生成了一个计数器,在每次 action 发送时被调用并进行了计数。
最后,将中间件应用到 Store 上:
const store = createStore( reducer, applyMiddleware(middleware) )
该中间件在每次 dispatch action 时会被调用,并在控制台打印计数器值。
总结
Redux 和 VueX 都有中间件的概念,它们允许将处理过程拆分成多个步骤。Redux 中间件的实现比 VueX 更简单,同时它还支持特定 action 的中间件。VueX 中间件允许监听特定模块的 mutation,并支持通过插件的方式添加全局中间件。无论是 Redux 还是 VueX,它们的中间件机制都允许我们以非常灵活的方式管理应用程序的状态。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a6700aadd4f0e0fff39dc4