React-redux源码

64 阅读2分钟

1.数据管理问题?

为了解决状态中的数据管理问题,因为在React中,数据是单向流动的,所以如果两个组件没有组件的关系,通信起来比较麻烦。

2.设计思想?

Redux会将整个应用的状态保存在一个地方,称为仓库,在仓库里保存一颗状态树,

组件可以派发动作给仓库,仓库内部会更具这个动作计算新的状态

组件可以订阅仓库中的状态变化更刷新自己的视图

redux虽然一般和react一起使用,但是两者不是强耦合的。

3.使用

通过createStore创建仓库,创建仓库的时候需要提供一个reducer计算新状态的函数,可以根据状态和派发的动作生成新的状态 可以通过store.dispatch方法向仓库派发动作 仓库收到派发的动作后调用reducer函数来计算新的状态,当仓库的状态发生变化后重新执行渲染方法 其他组件还可以通过调用store.subscribe方法来订阅仓库的状态变化

实现createStore

// preloadedState 是默认初始状态, createStore的第二个参数
const createStore = (reducer, preloadedState) => {
    // 先在仓库的内部定义一个初始值,默认是undefined
    let state = preloadedState;
    // 监听函数的数组
    let listeners = []
    // 返回当前仓库中的状态
    function getState() {
        return state
    }
    // 向仓库派发一个动作
    function dispatch( action ) {
        // 把老状态和动作对象传递给reducer,计算出新的状态
        state = reducer(state, action);
        // 通知所有监听函数执行
        listeners.froEact(l => l())
        return action;
    }
    // 添加一个订阅函数,或者说添加一个监听函数
    function subscribe( listener ) {
        // 把订阅函数添加到监听数组中
        listeners.push( listener )
        return () => {
            // 返回一个取消监听函数的销毁函数
            let index = listeners.indexOf( listener );
            listeners.splice( index, 1 )
        }
    }
    // 派发一个初始化的action,目的是为了让redux的初始值生效
    dispatch( {type:'@@REDUX/INIT'} )
    retrun {
        getState,
        dispatch,
        subscribe,
        
    }
}
export default createStore

bindActionCreators

// 绑定action的创建者 actionCreator action的创建者,可以是一个actionCreator函数
const actionCreator = {
    add() {
        return {type: "ADD"}
    },
    minus() {
        return {tyoe: "MINUS"}
    }
}
//  也可以是多个actionCreator的函数的数组
//  dispatch 仓库用来派发动作的函数

function bindActionCreator ( actionCreators, dispatch ) {
    //绑定一个action的创建者,绑定后的新函数,调用绑定后的新函数之后可以自动派发动作
    return function ( ...args ) {
        return dispatch( actionCreators.apply(this, args) );
    }
}

export default bindActionCreators( actionCreators, dispatch ) {
    if( typeof actionsCreators === "function" ) {
        return bindActionCreator( actionCreators, dispatch )
    } 
    const boundActionCreators = {};
    for ( const key in actionCreators ) {
        cosnt actionCreator = actionCreators[key];
        if( typeof actionsCreators === "function" ) {
               boundActionCreators[key] = bindActionCreator( actionCreators, dispatch )
        }
    }
    return boundActionCreators
}