本文整顿下近期 redux、mobx 在 react 中的应用比照,大家能够依据集体爱好,正当应用
查看残缺 demo

redux 状态治理

redux 根本应用流程

首先把 redux 的根本应用步骤梳理一下
  1. createStore 创立状态汇合 store,初始化的时候参数是相干的 reducer 以及 middleware,上面将具体阐明
import { createStore, combineReducers, applyMiddleware } from "redux";// 初始化状态汇合const store = createStore(  // 合并 reducer  combineReducers({ counter: counterReducer, other: otherReducer }),  // 引入中间件  applyMiddleware(logger));
  1. react-redux 中的 Provider 组件接管创立的 store,并置于组件顶层
import { render } from "react-dom";import { Provider } from "react-redux";render(  <Provider store={store}>    <App />  </Provider>,  document.getElementById("app"));
  1. 定义 reducer 自定义行为与解决的 state
// 初始 stateconst INITIAL_STATE = {  step: 0,};// 抽离对外裸露的行为枚举export const counterActionEnum = {  step: "step",  reset: "reset",};// 定义 reducer 不同行为下的不同 state 解决export default function counterReducer(state = INITIAL_STATE, action) {  console.log("reducer@", state, action, INITIAL_STATE);  switch (action.type) {    case counterActionEnum.step:      return {        step: state.step + 1,      };    case counterActionEnum.reset:      return {        ...INITIAL_STATE,      };    default:      return state;  }}
  1. connect 链接 reducer 参加业务连接,裸露 storedispatch 到相干业务组件中
import React from "react";import { connect } from "react-redux";import { counterActionEnum } from "../reducers/counter";function Counter(props) {  const { counter, doStep, doReset } = props;  return (    <div>      <span>计步器:{counter.step}</span>      <button onClick={() => doStep()}>计步</button>      <button onClick={() => doReset()}>重置</button>    </div>  );}// 链接 reducer 与 Counterexport default connect(  // mapStateToProps 将 state 映射到组件的 props 中  (state) => ({ counter: state.counter }),  // mapDispatchToProps 将 dispatch 转发后的 action 映射到组件的 props 中  (dispatch) => ({    // 通过 dispatch 触发行为    doStep: () => dispatch({ type: counterActionEnum.step }),    doReset: () => dispatch({ type: counterActionEnum.reset }),  }))(Counter);

redux 数据流

下图能够形象的阐明 redux 在数据中的流程体现:

connect -> Component -> dispatch action -> store -> mapStateToProps -> Component update

引入 redux 中间件

这里思考下 redux 中间件的意义:

  1. 为什么须要有中间件机制?
  2. 中间件具体在数据流中如何体现?
  3. 中间件有哪些利用场景?

自定义中间件

这里咱们先手写一下中间件看看它具体处于数据流的哪一步?
// 自定义中间件规定const logger = ({ dispatch, getState }) => (next) => (action) => {  console.log("[logger before]:", action);  // 执行下一个 dispatch  const result = next(action);  console.log("[logger after]:", action, getState());  return result;};// ...// 初始化 store 时引入 logger middlewareconst store = createStore(  // 合并 reducer  combineReducers({ counter: counterReducer, other: otherReducer }),  // 引入中间件  applyMiddleware(logger));
引入中间件后执行一个 action 的打印后果如下:
[logger before]: {type: "step"}// dispatch actionreducer@ {step: 0} {type: "step"} {step: 0}[logger after]: {type: "step"} {counter: {…}}

以上打印能够看出 middleware 的能够劫持 dispatch action 向下执行,以此能够看出中间件的重大作用,能够交叉于 action 数据流走向:

  1. 比方我想在每次 dispatch action 前后做些什么;
  2. 比方我又想劫持某些 action 做些什么,这个时候也比拟不便;
  3. 再比方我想实现异步的 action 也能够在这一步去做劫持;

由此可见,redux middleware 意义重大

redux 异步 action

  1. 咱们看一下 redux-thunk 的源码,通过劫持 action 来扩大异步
其实 redux-thunk 的思路比较简单,劫持了 action function 的扩大
function createThunkMiddleware(extraArgument) {  return ({ dispatch, getState }) => (next) => (action) => {    // 劫持 action,对 action 提供了扩大,在扩大中本人去实现异步    if (typeof action === "function") {      return action(dispatch, getState, extraArgument);    }    return next(action);  };}const thunk = createThunkMiddleware();thunk.withExtraArgument = createThunkMiddleware;export default thunk;
  1. 简略来说,其实通过 mapDispatchToProps 中本人异步执行 dispatch 即可
function mapDispatchToProps(dispatch) {  return {    // 通过 dispatch 触发行为    doStep: () => {      // 1s 后执行 action      setTimeout(() => {        dispatch({ type: counterActionEnum.step });      }, 1000);    },    doReset: () => dispatch({ type: counterActionEnum.reset }),  };}

mobx 状态治理

mobx 根本应用流程

  1. 创立一个 store
定义一个 class,应用注解 @observable 使值可响应,应用 @action 定义响应办法
import { observable, action } from "mobx";class CounterStore {  @observable step = 0;  @action  doStep = () => {    this.step++;  };  @action  doReset = () => {    this.step = 0;  };}// 抛出一个实例export default new CounterStore();
  1. Provider 引入 counterStore
所有的 store 都在顶层通过 Provider 混入到全局
<Provider counterStore={counterStore}>  <div>    <h1>mobx 计步器</h1>    <CounterApp />  </div></Provider>
  1. inject 将须要的状态混入到组件的 props,并通过 observer 使组件可响应
// 将 counterStore 混入到 Counter 的 props 中const CounterApp = inject("counterStore")(observer(Counter));
  1. 组件中调用对应的 state 与 action
function Counter({ counterStore }) {  const { step, doStep, doReset } = counterStore;  return (    <div>      <span>计步器:{step}</span>      {"  "}      <button onClick={() => doStep()}>计步</button>      {"  "}      <button onClick={() => doReset()}>重置</button>    </div>  );}

mobx 数据流

mobx 的思路比较简单,通过 action -> state -> view,下图明确提现了 mobx 的数据交互流程

总结

redux 长处

  1. 流程标准,依照官网举荐的标准和联合团队格调打造一套属于本人的流程。
  2. 函数式编程,在 reducer 中,承受输出,而后输入,不会有副作用产生,幂等性。
  3. 可追踪性,很容易追踪产生 BUG 的起因。

redux 毛病

  1. 晦涩太繁琐,须要写各种 type、action、reducer,不易上手,初学者可能会感觉比拟绕。
  2. 同步数据流,异步须要援用其余库(redux-thunk/redux-saga 等)或者通过异步 dispatch 的技巧。

mobx 长处

  1. 容易上手,class 中治理 state、action,应用简略,基于 Proxy 实现的数据响应式。
  2. 写更少的代码,实现更多的事。不会跟 redux 一样写十分多的 action、type。
  3. 使组件更加颗粒化拆分,并且业务更加容易形象。

mobx 毛病

  1. 过于自在,mobx 提供的约定及模版代码很少,如果团队不做一些约定,容易导致团队代码格调不对立。