React 之 Redux

React 之 Redux

Redux

JavaScript 状态容器,提供可预测的状态管理

核心流程

在这里插入图片描述

  • Store: 存储状态的容器,JavaScript对象
  • View: 视图,HTML⻚面
  • Actions: 对象,描述对状态进行怎样的操作
  • Reducers:函数,操作状态并返回新的状态

常用api

// 创建 Store 状容器
const store = Redux.createStore (reducer);
// 创建用于处理状态的 reducer 函数
function reducer (state = initialstate, action){};
// 获取状态  
store.getState ();
// 订阅状态
store.subscribe (function () {} );
// 触发 Action
store dispatch ({type: 'description... '));

项目中的使用

下载

npm install redux react-redux

Provider 组件与 connect 方法

Provider

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

connect

import { connect } from 'react-redux';
const mapStateToProps = state => ({
	count: state.count
});
const mapDispatchToProps = dispatch => ({
	increment () {
		dispatch({ type: 'increment' })
	}
});
export default connect(mapStateToProps, mapDispatchToProps)(组件名称)

redux中间件

工作流程

在这里插入图片描述

中间件模板
export default store => next => action => { }
注意:结尾必须添加,next(action)
import { createStore, applyMiddleware } from "redux";
import thunk from 'redux-thunk';
const store = createStore(RootReducer, applyMiddleware(thunk));
常用中间件
  • redux-saga、redux-thunk 都是处理异步调用
  • redux-actions 简化redux 中action写法;

action

import { createAction } from 'redux-actions'

export const increment = createAction('increment')
export const decrement = createAction('decrement')
export const increment_async = createAction('increment_async')

reducer

import { handleActions as createReducer } from 'redux-actions';
import { increment, decrement } from '../actions/counter.action';

const initState = {
  count: 0
}

const IncrementHandle = (state, action) => ({count: state.count + action.payload })
const DecrementHandle = (state, action) => ({count: state.count - action.payload })

export default createReducer({
  ['increment']: IncrementHandle,
  ['decrement']: DecrementHandle,
}, initState)

redux 核心模拟实现

function createStore (reducer, preloadedState, enhancer) {
  // reducer 类型判断 
  if (typeof reducer !== 'function') throw new Error('redcuer必须是函数');

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('enhancer必须是函数')
    }
    return enhancer(createStore)(reducer, preloadedState);
  }
  // 状态
  var currentState = preloadedState;
  // 订阅者
  var currentListeners = [];
  // 获取状态
  function getState () {
    return currentState;
  }
  // 用于触发action的方法
  function dispatch (action) {
    // 判断action是否是一个对象
    if (!isPlainObject(action)) throw new Error('action必须是一个对象');
    // 判断action中的type属性是否存在
    if (typeof action.type === 'undefined') throw new Error('action对象中必须有type属性');
    // 调用reducer函数 处理状态
    currentState = reducer(currentState, action);
    // 调用订阅者 通知订阅者状态发生了改变
    for (var i = 0; i < currentListeners.length; i++) {
      var listener = currentListeners[i];
      listener();
    }
  }
  // 订阅状态的改变
  function subscribe (listener) {
    currentListeners.push(listener);
  }

  // 默认调用一次dispatch方法 存储初始状态(通过reducer函数传递的默认状态)
  dispatch({type: 'initAction'})

  return {
    getState,
    dispatch,
    subscribe
  }
}

// 判断参数是否是对象类型
// 判断对象的当前原型对象是否和顶层原型对象相同
function isPlainObject (obj) {
  if (typeof obj !== 'object' || obj === null) return false;
  var proto = obj;
  while (Object.getPrototypeOf(proto) != null) {
    proto = Object.getPrototypeOf(proto)
  }
  return Object.getPrototypeOf(obj) === proto;
}

function applyMiddleware (...middlewares) {
  return function (createStore) {
    return function (reducer, preloadedState) {
      // 创建 store
      var store = createStore(reducer, preloadedState);
      // 阉割版的 store
      var middlewareAPI = {
        getState: store.getState,
        dispatch: store.dispatch
      }
      // 调用中间件的第一层函数 传递阉割版的store对象
      var chain = middlewares.map(middleware => middleware(middlewareAPI));
      var dispatch = compose(...chain)(store.dispatch);
      return {
        ...store,
        dispatch
      }
    }
  }
}

function compose () {
  var funcs = [...arguments];
  return function (dispatch) {
    for (var i = funcs.length - 1; i >= 0; i--) {
      dispatch = funcs[i](dispatch);
    }
    return dispatch;
  }
}

function bindActionCreators (actionCreators, dispatch) {
  var boundActionCreators = {};
  for (var key in actionCreators) {
    (function (key) { //将key传入使其在内存中不释放
      boundActionCreators[key] = function () {
        dispatch(actionCreators[key]())
      }
    })(key)
  }
  return boundActionCreators;
}

function combineReducers (reducers) {
  // 1. 检查reducer类型 它必须是函数
  var reducerKeys = Object.keys(reducers);
  for (var i = 0; i < reducerKeys.length; i++) {
    var key = reducerKeys[i];
    if (typeof reducers[key] !== 'function') throw new Error('reducer必须是函数');
  }
  // 2. 调用一个一个的小的reducer 将每一个小的reducer中返回的状态存储在一个新的大的对象中
  return function (state, action) {
    var nextState = {};
    for (var i = 0; i < reducerKeys.length; i++) {
      var key = reducerKeys[i];
      var reducer = reducers[key];
      var previousStateForKey = state[key];
      nextState[key] = reducer(previousStateForKey, action)
    }
    return nextState;
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值