redux和mobx, 他们的思想都是一样的,都是解决跨组件数据传输的问题。实现数据持久化。
他们都可以应用于React(用于构建用户界面的 JavaScript 库)。
为什么我们需要统一的状态管理呢?
如果props能满足项目需求,我们可以不用引入redux或mobx,当遇到多层级,数据跨组建传输的场景,我们就可以引入状态管理,将他们放在顶层。
这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。
拿我们云管平台举例,属于框架的功能:
权限管理(每个页面需要查用户和用户权限) 数据中心(很多页面需要拿数据中心id) 系统配置 或者,属于数据传递层级比较深,用的较多的功能:虚拟机等
下面我们分别看看redux和mobx的异同:
一、Redux
Redux 是什么 ? Redux 是前端应用的状态容器,提供可预测的状态管理,其基本定义可以用下列公式表示:
(state, action) => newState
其特点可以用以下三个原则来描述。
-
**单一数据源**:在 `Redux` 中,整个应用的状态以状态树的形式,被存储在一个单例的 `store` 中。
-
**状态数据只读**:惟一改变状态数据的方法是触发 `action`,`action` 是一个用于描述已发生事件的普通对象。
-
**使用纯函数修改状态**:在 `Redux` 中,通过纯函数,即 `reducer` 来定义如何修改 `state`。
从上述原则中,可以看出,构成 Redux 的主要元素有 action、reducer、store
Redux 具有单一数据源,触发 action 时,Redux store 在执行状态更新逻辑后,会执行注册在 store 上的事件处理函数。
代码:
//view登陆
//以AD/LDAP方式登录
loginADLDAP = () => {
const { validateFieldsAndScroll } = this.props.form;
validateFieldsAndScroll((errors, values) => {
if (errors) {
return;
}
const loginType = 'ADLDAP';
this.setState(values, () => {
this.props.dispatch(login(values, loginType));
});
});
};
//action
export function loginPost(json,project) {
return {
type: LOGIN,
login: json,
loginProject:project
}
}
(以上是云管登陆代码截图)
-
`dispatch` 是 `View` 发出 `Action` 的唯一方法(事件)
-
`Store` 收到 `Action` 以后,必须给出一个新的 `State`,这样 `View` 才会发生变化。这种 `State` 的计算过程就叫做 `Reducer`。
-
`Reducer` 是一个函数,它接受 `Action` 和当前 `State` 作为参数,返回一个新的 `State`。
以上就是redux的基本介绍,延伸的还有redux的异步处理方案,中间件,应用状态的扁平化等,不赘述。
二 Mobx
任何源自应用状态的东西都应该自动地获得。其中包括UI、数据序列化、服务器通讯,等等。
React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。
Mobx 是一个简单、可扩展的前端应用状态管理工具。Mobx 背后的哲学很简单:当应用状态更新时,所有依赖于这些应用状态的观察者(包括UI、服务端数据同步函数等),都应该自动得到细粒度地更新。
核心概念:
Observable state(可观察的状态)
MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。
通过使用 @observable 装饰器(ES.Next)来给你的类属性添加注解就可以简单地完成这一切。
另外:
Derivations 可以理解为衍生,它是应用状态的观察者。
Mobx 中有两种形式的衍生,分别是 Computed values 和 Reactions。
Computed values(计算值)
使用 MobX, 你可以定义在相关数据发生变化时自动更新的值。Computed values 是计算属性,它的数据通过纯函数由应用状态计算得来,当依赖的应用状态变更时,Mobx 自动触发计算属性的更新。
Reactions(反应)
Reactions 可简单理解为响应,与计算属性类似,它响应所依赖的应用状态的变更,不同的是,它不产生新的数据,而是输出相应的副作用(side effects),比如更新UI。
Actions
Actions 可以理解为动作,由应用中的各类事件触发。Actions 是变更应用状态的地方,可以帮助你更加清晰的组织你的代码。
下面这张图,反应了他们之间的关系。
可以有多个
//获取部门树
@action getDeptTree = (params) => {
userService.getDeptTree(params).then(rs => {
runInAction(() => {
this.deptTree = rs.data
})
})
}
componentDidMount() {
this.props.userStore.getGroupTree(true)
}
render() {
const { groupTree=[] } = this.props.userStore
}
-
可以有多个`store`,把需要公用的数据,都放里面。规范,`store`里面到底放什么内容?
-
定义观察对象,接口获取数据,给对象。
-
需要的时候,直接从store里面拿。
-
其他的页面或者模块,也可以修改对象或者拿对象。
两者的区别:
| redux | mobx | |
|---|---|---|
| 核心模块 | Action,Reducer,Store,没有调度器的概念; | Action,Reducer,Derivation |
| store | 只有一个 Store, Store 和更改逻辑是分开的,带有分层 reducer的单一 Stor | 有多个 store |
| 状态 | 状态是不可改变的 | 通常将状态包装成可观察对象,一旦状态对象变更,就能自动获得更新 |
| 编程思想 | 更多的是遵循函数式编程思想 | 设计更多偏向于面向对象编程和响应式编程 |
| 对象 | JavaScript对象 | 可观察对象 |
单一store和多store
store是应用管理数据的地方,在Redux应用中,我们总是将所有共享的应用数据集中在一个大的store中,而Mobx则通常按模块将应用状态划分,在多个独立的store中管理。
JavaScript对象和可观察对象
Redux默认以JavaScript原生对象形式存储数据,而Mobx使用可观察对象: Redux需要手动追踪所有状态对象的变更;
Mobx中可以监听可观察对象,当其变更时将自动触发监听;
选择Mobx的原因
-
学习成本少:Mobx基础知识很简单,学习了半小时官方文档和示例代码就搭建了新项目实例;而Redux确较繁琐,流程较多,需要配置,创建store,编写reducer,action,如果涉及异步任务,还需要引入
redux-thunk或redux-saga编写额外代码,Mobx流程相比就简单很多,并且不需要额外异步处理库; -
面向对象编程:Mobx支持面向对象编程,我们可以使用@observable and @observer,以面向对象编程方式使得JavaScript对象具有响应式能力;而Redux最推荐遵循函数式编程,当然Mobx也支持函数式编程;
-
模版代码少:相对于Redux的各种模版代码,如,
actionCreater,reducer,saga/thunk等,Mobx则不需要编写这类模板代码;
不选择Mobx的可能原因
-
**过于自由**:Mobx提供的约定及模版代码很少,这导致开发代码编写很自由,如果不做一些约定,比较容易导致团队代码风格不统一,所以当团队成员较多时,确实需要添加一些约定;
-
**可拓展,可维护性**:也许你会担心Mobx能不能适应后期项目发展壮大呢?确实Mobx更适合用在中小型项目中,但这并不表示其不能支撑大型项目,关键在于大型项目通常需要特别注意可拓展性,可维护性,相比而言,规范的Redux更有优势,而Mobx更自由,需要我们自己制定一些规则来确保项目后期拓展,维护难易程度;当然对于“Redux更规范,更靠谱,应该使用Redux”或”Redux模版太多,太复杂了,应该选择Mobx”这类推断,我们也应该避免,这些都是相对而言。
每个框架都有各自的实现,特色,及其适用场景,正比如Redux流程更复杂,但熟悉流程后就更能把握它的一些基础/核心理念,使用起来可能更有心得及感悟;
而Mobx简单化,把大部分东西隐藏起来,如果不去特别研究就不能接触到它的核心/基本思想,也许使得开发者一直停留在使用层次。
所以无论是技术栈还是框架。类库,并没有绝对的比较我们就应该选择什么,抛弃什么,我们应该更关注它们解决什么问题。
它们解决问题的关注点,或者说实现方式是什么,它们的优缺点还有什么,哪一个更适合当前项目,以及项目未来发展。