关于前端:React-状态管理对比

源码:地址

在应用 React 过程中应用状态治理的抉择切实是太多,这里只找这三种尝试比照

  • React Redux
  • Mobx
  • dva

React Redux

官网

单项数据流治理

须要下载依赖

yarn add redux react-redux redux-thunk

Provider

通过 Provider 组件来包裹 app 能够使得全局来拜访咱们的 store

import { Provider } from 'react-redux'
import store from './store'
...
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
)

connect

connect 连贯组件和状态治理

import { connect } from 'react-redux'
import { addCount } from './store/redux'

// ReduxDemo 组件

const mapStateToProps = state => {
  return {
    num: state.num.count
  }
}

const mapDispatchToProps = dispatch => ({
  add() {
    dispatch(addCount())
  }
})

export default connect(mapStateToProps, mapDispatchToProps)(ReduxDemo)

store 套路

  • 定义常量
  • 定义 actions
  • 编写 reducer
  • 创立 store
import { createStore, compose, applyMiddleware, combineReducers } from 'redux'
import thunk from 'redux-thunk'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
// 常量
export const ADD = 'demo/add_conut'

// actions
export const changeCount = ({count}) => ({
  count,
  type: ADD
})
export const addCount = () => {
  return (dispatch, getState) => {
    let _state = getState()
    _state.num.count++;
    dispatch(changeCount(_state.num))
  }
}
// reducer
const defaultState = {
  count: 0
}

const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case ADD:
      return Object.assign({}, state, { count: action.count });
    default:
      return state;
  }
}
// store
export default createStore(
  // 模块化 reducer
  combineReducers({
    num: reducer // store 中能够定义不同模块
  }),
  composeEnhancers(
    applyMiddleware(thunk)
  )
);

Mobx

文档

双向数据流绑定

装置依赖

yarn add mobx mobx-react

Mobx 创立 store 绝对简略

store 的不同的形式

  • 对象形式
import {observable, action, computed, makeAutoObservable, makeObservable } from 'mobx';

// 对象
const store = makeObservable(
  {
    count: 0,
    get double() {
      return this.count * 2;
    },
    addCount() {
      this.count += 1;
    },
    subCount() {
      this.count -= 1;
    }
  },
  // 对属性进行包装,用于标记属性的作用
  {
    count: observable, // 响应属性
    double: computed, // 计算属性
    addCount: action, // action 办法,扭转响应属性
    subCount: action
  }
)

export default store

makeObservable 能够创立一个响应式对象,与 Vue 3.0 相似,传入的对象属性也是通过 Proxy 代理

makeAutoObservable 则更弱小,能够主动为对象属性包装函数

import { makeAutoObservable } from 'mobx';

// 对象
const store = makeAutoObservable(
  {
    count: 0,
    get double() {
      return this.count * 2;
    },
    addCount() {
      this.count += 1;
    },
    subCount() {
      this.count -= 1;
    }
  }
)
  • 类形式
class Store {
  constructor() {
    makeAutoObservable(this)
  }
  count = 0
  get double() {
    return this.count * 2;
  }
  addCount() {
    this.count += 1;
  }
  subCount() {
    this.count -= 1;
  }
}
export default new Store()

注入 store 与连贯组件

App.js 中注入 store

import { Provider } from 'mobx-react'
import store from './store/mobx';
import Mobx from './Mobx.jsx';

const App = () => {
  return (
    <div>
      <Provider store={store}>
        <Mobx />
      </Provider>
    </div>
  )
}

这里的 Provider 组件中的 propsstore,它是能够任由咱们自定义的,而在组件中连贯须要传入这个 props 变量名

import { inject, observer } from 'mobx-react'

function MobxDemo({store}) {
  return (
    <div>
      <h2>Mobx</h2>
      <p>点击数:{store.count}</p>
      <p>计算属性单数:{store.double}</p>
      <button onClick={() => store.addCount()}>点击 +</button>
      <button onClick={() => store.subCount()}>点击 -</button>
    </div>
  )
}

export default inject('store')(observer(MobxDemo));

组件通过 inject 注入咱们须要传入的 store,组件通过 props.store 属性拜访

dva

文档

dva 是一个的 React 利用框架,简化 API,让开发 React 利用更加不便和快捷。

dva = React-Router + Redux + Redux-saga

依赖装置

yarn add dva

应用

须要实例化 dva

import React from 'react'
import dva, { connect } from 'dva';
import dvaModel from './store/dva';
import DvaDemo from './Dva.jsx'

const createHistory = require("history").createHashHistory

const history = createHistory()

// 创立利用
const app = dva({
  history: createHistory()
});
app.model(dvaModel)
// 注册视图
app.router(() => <DvaDemo />);
// 启动利用
app.start('#app');

model

创立一个 model 数据,根本的属性

  • namespace 空间命名,全局惟一
  • state 初始数据
  • reducers 批改数据,相似 vuex 中的 mutations
  • effects 获取数据, 相似 vuex 中的 action
  • subscription 订阅数据
const model = {
  namespace: 'dvamodel',
  state: {
    name: 'model dva',
    count: 0
  },
  reducers: {
    add(state) {
      state.count = state.count + 1
      return {
        ...state
      }
    },
    sub(state) {
      state.count = state.count - 1
      return {
        ...state
      }
    }
  },
  effects: {
    *addCount(action, { call, put }) {
      console.log(action, action.payload) // 拿到传入的 payload
      yield put({type: 'add'})
    },
    *subCount(action, { call, put }) {
      console.log(action, action.payload) // 拿到传入的 payload
      yield put({type: 'sub'})
    }
  },
}

export default model

连贯组件

应用 connect 连贯组件,都挂到 props 中去

import React from 'react'
import { connect } from 'dva'

function DvaDemo({dvamodel, dispatch}) {
  console.log(dvamodel) // 通过命令空间拜访
  return (
    <div>
      <h2>Dva</h2>
      <p>点击数:{dvamodel.count}</p>
      <button onClick={() => dispatch({
        type: 'dvamodel/addCount',
        payload: 1
      })}>点击 +</button>
      <button onClick={() => dispatch({
        type: 'dvamodel/subCount',
        payload: 1
      })}>点击 -</button>
    </div>
  )
}

export default connect((props) => props)(DvaDemo);

总结

通过简略的应用尝试,感觉还是 Mobx 是最简略

欢送关注【前端学啥】一起交换

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理