概述
redux 和 vuex 都提供了一套 状态管理机制 帮助我们在 单页面应用 中管理 公共状态- state。 尽管它们两个的 应用场景不同,但是我们还是可以对它们做一些分析比较。
相同
首先我们来分析一下它们的 相同之处,整理如下:
-
状态管理机制相同
两者的 状态管理机制 都是基于 状态、状态更新、触发状态修改 这三个要素进行的。
这三个要素,在 redux 中对应为 state、 reducer、 dispatch,在 vuex 中对应为 state、mutation、commit。其中,state 用于存储状态,reducer(mutation) 用于更新 state, dispatch(commit) 用于触发 state 更新。
不管是使用 redux 还是 vuex,我们都会先构建一个 store 对象来存储 state, 然后在应用中的 组件 中使用 store.state。 当需要更新 state 时,在 组件 中通过 dispatch( 或者 commit) 触发 state 更新, 然后使用 reducer(mutation) 来更新 state。
state 更新以后,会触发相应的组件更新,重新渲染。
-
响应式更新机制相同
我们知道, 在 redux 和 vuex 中, 当 state 发生变化时,应用 state 的 组件 会 响应式更新。
尽管实现细节不同,但两者都是基于 观察者模式 实现 响应式更新 的。即 state 维护一个 依赖列表 - deps,使用 state 的 组件 都会添加到这个 依赖列表 中。当 state 发生变化时,通知 依赖列表 中的 组件 更新。
-
修改 state 的过程都是同步的
不管是 reducer 还是 mutation,在 更新 state 时,都是 同步 的。即我们调用 dispatch 或者 commit 以后,能 立即拿到最新的 state。
-
都提供了异步更新 state 的措施
在 vuex 中,我们可以在 action 中异步更新 state。在 redux 中, 我们可以借助中间件 redux-thunk 实现 异步更新 state。
尽管可以异步, 但最后实际更新 state 时, 依然要通过 dispatch 或者 commit 来更新 state。
-
都不建议直接修改 state
不管是在 redux 还是 vuex 中, 都不建议 直接修改 state, 而是通过 dispatch(或者 commit) 来更新 state。
首先,直接修改 state,devtools 无法追踪 state 的变化。
其次,在 redux 中如果 直接修改 state,无法通知 相应的组件 进行 响应式更新。
-
应用中所有组件访问的都是同一个 store 对象
不管是在 react 应用 还是 vue 应用,应用中所有组件访问的 store 对象 都是 同一个 store 对象。
不同
两者的 不同之处, 整理如下:
-
应用范围不同
redux 是一个 通用的状态管理机制,不依赖于 react, 通过 react-redux 可应用于 react 应用。
vuex 不同, 它 依赖于 vue, 无法用在非 vue 应用场景。
-
响应式更新实现不同
尽管 redux 和 vuex 的 响应式更新机制 都是基于 观察者模式 实现的,但是它们的 实现 不同。
在 redux 中, store 对象 会维护一个 依赖列表 - deps, 应用 store.state 的 组件 都会添加到 依赖列表中。 当 组件 调用 diaptch 触发 state 更新时, store 对象 会通知 依赖列表 中的 组件 去更新。需要更新的组件,在 重新渲染 之前,会先 比较使用的 state 是否发生变化。只有使用的 state 发生变化,组件才会重新渲染。
在 vuex 中, state 对象 中的 每一个 state, 都会维护一个 依赖列表 - deps。 应用 state 的组件 会添加到 对应 state 的依赖列表 中。 当某个 state 发生变化时,通知 依赖列表 中的 组件 更新, 重新渲染。
由于 响应式更新实现不同,在 redux 中 直接修改 state(不通过 dispatch),不会触发响应式更新;而在 vuex 中,直接修改 state 可以触发响应式更新,只不过不建议这么做。
-
store 引入应用的方式不同
不管是 redux 还是 vuex, 使用之前都需要 构建一个 store 对象,然后把 store 对象 引入到应用中。 不过两者的 引入方式 不同。
在 redux 中,store 对象会通过 react-redux 提供的 Provider 添加到 react 应用 中。在 react 应用 启动过程中,会先通过 createContext 构建一个 全局 Context 对象,store 对象 会保存到 Context 对象 的 value 值中。所有包裹在 Provider 中的 组件 都可以通过 全局 Context 对象 的 value 值访问 store 对象。
在 vuex 中,store 对象 会在 vue 应用 启动过程中, 添加到 根vue实例 的 $store 属性 上,所有 子组件 $store 属性 都链接到 根vue实例 $store 属性 上。所有的 vue组件实例 都可以通过 $store 属性 访问 store 对象。
-
多个 reducer(mutation) 处理方式不同
不管是使用 redux 还是 vuex, 我们都会遇到需要定义 多个 reducer(mutation) 的情况。此时,两者在需要更新 state 时,处理方式不同。
在 redux 中,当我们通过 dispatch 触发 state 更新时, 会把 所有的 reducer 都执行一遍。
而在 vuex 中, 我们通过 commit 触发 state 更新 时,会 指定 mutation 执行,不相关的 mutation 不触发。