redux剖析

redux

redux是flux的进化版,flux流程图(图片来源:http://caibaojian.com/react/flux.html):
在这里插入图片描述

Redux流程图

在这里插入图片描述

combineReducers

function combineReducers(reducers) {
    const reducerKeys = Object.keys(reducers);
    // 组合后的reducer
    const finalReducers = {};
    // 如果ruducer不是函数,将其过滤
    for(let i=0, len=reducerKeys.length; i<len; i++) {
        let key = reducerKeys[i];
        if (typeof reducers[key] === 'function') {
            finalReducers[key] = reducers[key];
        }
    }

    const finalReducerKeys = Object.keys(finalReducers);

    // 返回值为组合后的reducer函数,返回总的state
    return function combination(state={}, action) {
        // state是否改变
        let hasChanged = false;
        // 改变后的state
        let nextState = {};
        for (let i=0, len=finalReducerKeys.length; i<len; i++) {
            let key = finalReducerKeys[i];
            // 获取key对应的reducer
            let reducer = finalReducers[key];
            // state树与finalReducers的key是一一对应的
            let preStateForKey = state[key];
            // 执行reducer获取nextState
            let nextStateForKey = reducer(preStateForKey, action);

            nextState[key] = nextStateForKey;

            hasChanged = hasChanged || nextStateForKey !== preStateForKey;
        }
        // 如果状态改变,返回nextState; 否则返回state;
        return hasChanged ? nextState : state;
    }
}

createStore

function createStore(reducer, enhancer) {
	if (enhancer) {
		return enhancer(createStore)(reducer);
	}
    let currentState = {};
    let currentListeners = [];
    let isDispatching = false;
    function getState() {
        return currentState
    }
    function subscribe(listener) {
        currentListeners.push(listener);
        let isSubscribed = true;
          // 返回一个取消订阅函数
		return function unsubscribe() {
		    if (!isSubscribed) {
		      return
		    }
		
		    if (isDispatching) {	// reducer是否正在执行
		      throw new Error(
		        'You may not unsubscribe from a store listener while the reducer is executing. ' +
		          'See http://redux.js.org/docs/api/Store.html##subscribe for more details.'
		      )
		    }
		
		    isSubscribed = false	// 重置已订阅标志位

		    const index = currentListeners.indexOf(listener)
		    currentListeners.splice(index, 1)
		  }
    }
    function dispatch(action) {
    	try {
    		isDispatching = true;
    		currentState = reducer(currentState, action);
    	} finally {
			isDispatching = false
		}
        
        currentListeners.forEach(listener => {
            listener();
        })
        
        return action;
    }
    return {getState, subscribe, dispatch};
}

applyMiddleware

可以参考我的另一篇博客redux applyMiddleware

// middleware: ({ getState, dispatch }) => next => action;
// midddleware只是包装了store的dipatch方法
function logger ({ getState }) {
    return (next) => (action) => {
        console.log('will dispatch: ', action);
        let returnValue = next(action);
        return returnValue;
    }
}
function applyMiddleware (...middlewares) {
    return createStore => (...args) => {
        const store = createStore(...args);
        const dispatch = store.dispatch;

        const middlewareAPI = {
            getState: store.getState,
            dispatch: (...args) => dispatch(...args)
        }
        const chain= middlewares.map(middleware => middleware(middlewareAPI))
        dispatch = compose(...chain)(store.dispatch);

        return {
            ...store,
            dispatch
        }
    }
}

compose

// 从右到左返回合成后的函数
function compose(...funcs) {
    if (funcs.length === 0) {
        return arg => arg
    }
    if (funcs.length === 1) {
        return funcs[0];
    }
    return funcs.reduce((a, b) => (...args) => a(b(...args)));
}

function add (x) {return x + 1}
function pow (x) {return Math.pow(x, 2)}

compose()(3);         // 3
compose(add, pow)(3); // 10
compose(pow, add)(3); // 16

react-redux

Provider

class Provider extends React.Component {
    static childContextTypes = {
        store: PropTypes.object
    }
    constructor(props, context) {
        super(props, context);
        this.store = props.store;
    }
    getChildContext() {
        return {store: this.store};
    }
    render() {
        return this.props.children;
    }
}

connect

const connect = (mapStateToProps = state => state, mapDispatchToProps = {}) => {
    (WrapContainer) => {
        return class ConnectComponent extends React.Component {
            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 = bindActionCreator(mapDispatchToProps, store.dispath);
                this.setState({
                    props: {
                        ...this.state.props,
                        ...stateProps,
                        ...dispatchProps
                    }
                })
            }
            render() {
                return <WrapContainer {...this.state.props}></WrapContainer>
            }
        }
        
    }
}

参考文献

  1. 前端进阶之道
  2. redux源码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neil-

你们的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值