Provider
// Provider把store放到context里,所有的子元素可以直接取到storeimport React from 'react'import PropTypes from 'prop-types'import {bindActionCreators} from './utils.js'export const connect = (mapStateToProps=state=>state,mapDispatchToProps={})=>(WrapComponent)=>{ return class ConnectComponent extends React.Component{ static contextTypes = { store:PropTypes.object } constructor(props, context){ super(props, context) this.state = { props:{} } } componentDidMount(){ const {store} = this.context store.subscribe(()=>this.update()) this.update() } update(){ const {store} = this.context const stateProps = mapStateToProps(store.getState()) const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch) this.setState({ props:{ ...this.state.props, ...stateProps, ...dispatchProps } }) } render(){ return } }}export class Provider extends React.Component{ static childContextTypes = { store: PropTypes.object } getChildContext(){ return {store:this.store} } constructor(props, context){ super(props, context) this.store = props.store } render(){ return this.props.children }}
utils.js
export function createStore(reducer, enhancer){ if (enhancer) { return enhancer(createStore)(reducer) } let currentState = {} let currentListeners = [] function getState(){ return currentState } function subscribe(listener){ currentListeners.push(listener) } function dispatch(action){ currentState = reducer(currentState, action) currentListeners.forEach(v=>v()) return action } dispatch({type:'@IMOOC/WONIU-REDUX'}) return { getState, subscribe, dispatch}}// 自定义applyMiddleware函数export function applyMiddleware(...middlewares){ return createStore=>(...args)=>{ const store = createStore(...args) let dispatch = store.dispatch const midApi = { getState:store.getState, dispatch:(...args)=>dispatch(...args) } const middlewareChain = middlewares.map(middleware=>middleware(midApi)) dispatch = compose(...middlewareChain)(store.dispatch) return { ...store, dispatch } }}// 自定义compose函数export function compose(...funcs){ if (funcs.length==0) { return arg=>arg } if (funcs.length==1) { return funcs[0] } return funcs.reduce((ret,item)=> (...args)=>ret(item(...args)))}function bindActionCreator(creator, dispatch){ return (...args) => dispatch(creator(...args))}export function bindActionCreators(creators,dispatch){ return Object.keys(creators).reduce((ret,item)=>{ ret[item] = bindActionCreator(creators[item],dispatch) return ret },{})}