自定义redux和react-redux

redux库
向外暴露的几个函数
createStore():接收的参数为reducer函数,返回为store对象、
combineReducers():接收包含n个的reducer方法,返回一个新的reducer函数
 
store对象的内部结构
getState():返回值为内部保存的state数据
dispatch():参数为action对象,触发reducer调用
subsrcibe():参数为监听内部state更新的回调
 
自定义redux库
/**
 * redux库的主模块
 * createStore():接收的参数为reducer函数,返回为store对象、
combineReducers():接收包含n个的reducer方法,返回一个新的reducer函数

store对象的内部结构
getState():返回值为内部保存的state数据
dispatch():参数为action对象,触发reducer调用
subsrcibe():参数为监听内部state更新的回调
 */
//根据指定的reducer函数创建一个store对象
export function createStore(reducer) {
    //用来存储内部状态数据的变量,初始值为调用reducer的返回的结果
    let state = reducer(null, { type: '@@redux/int' })
    //用来存储监听状态更新回调函数的数组容器
    const listeners = []
    //返回当前内部state的数据 
    function getState() {
        return state
    }
    //分发action,
    //1.触发reducer调用,从而产生新的state
    //2.保存新的state
    //3.调用所有已存在的监视回调函数
    function dispatch(action) {
        const newState = reducer(state, action)
        state = newState
        listeners.forEach(listener => listener())

    }
    //绑定内部state改变的监听回调,可以绑定多个监听,可以调用多次
    function subsrcibe(listener) {
        //保存到缓存listener的容器数组中
        listeners.push(listener)
    }
    //返回store对象
    return {
        getState,
        dispatch,
        subsrcibe

    }
}
//方法一
//整合传入参数的多个reducer函数,返回一个新的reducer
//新的reducer管理的总状态:{r1:state1,r2:state2}
export function combineReducers(reducers) {
    //返回一个新的总的reducer函数
    //state:总状态
    return (state, action) => {
        const totalState = {}
        //执行reducers中每个reducer函数,得到一个新的子状态,并封装到一个对象容器中
        Object.keys(reducers).forEach(key => {
            totalState[key] = reducers[key](state[key], action)
        })
        //返回总状态对象
        return totalState


    }
}
//方法二:
export function combineReducers(reducers) {
    //返回一个新的总的reducer函数
    //state:总状态
    return (state = {}, action) => {
        return Object.keys(reducers).reduce((totalState, key) => {
            totalState[key] = reducers[key](state[key], action)
            return totalState
        }, {})

    }
}
React-redux暴露的两个api
Provider
connect
 
Provider组件
接收store属性
让所有容器组件都可以看到store,从而通过store读取/更新状态
 
connect函数
接收2个参数:mapStateToProps和mapDispatchToProps
mapStateToProps:为一个函数,用来指定项UI组件传递哪些一般属性
mapDispatchToProps:为了一个函数或对象,用来指定向UI组件传递哪些函数属性
connect()执行的返回值为一个高阶组件:包装UI组件,返回一个新的容器组件
 容器组件会向UI传入前面指定的一般/函数类型属性 
import React from 'react'
import PropTypes from 'prop-types'
/**
 * react-redux库模块
 * React-redux暴露的两个api
 * Provider
connect

Provider组件
接收store属性
让所有容器组件都可以看到store,从而通过store读取/更新状态

connect函数
接收2个参数:mapStateToProps和mapDispatchToProps
mapStateToProps:为一个函数,用来指定项UI组件传递哪些一般属性
mapDispatchToProps:为了一个函数或对象,用来指定向UI组件传递哪些函数属性
connect()执行的返回值为一个高阶组件:包装UI组件,返回一个新的容器组件
 容器组件会向UI传入前面指定的一般/函数类型属性

 */
//用来向所有的容器组件提供store的组件类
//通过context向所有的容器组件传递store
export class Provider extends React.Component {
    static propTypes = {
        store: PropTypes.object.isRequired//声明接收store对象
    }
    //声明提供的context的数据名称和类型
    static childContextTypes = {
        store: PropTypes.object
    }
    //向所有有声明子组件提供包含要传递数据的context对象
    getChildContext() {
        return {
            store: this.props.store
        }
    }
    render() {
        //返回渲染《Provider》的所有子节点
        return this.props.children
    }

}
//connect高阶函数:接收两个参数mapStateToProps和mapDispatchToProps
//返回一个高阶组件函数
//高阶组件接收一个UI组件,返回一个容器组件
export function connect(mapStateToProps, mapDispatchToProps) {
    //返回高阶组件函数
    return (UIComponent) => {
        //返回容器组件
        return class ContainerComponent extends React.Component {
            //声明接收的context数据的名称和类型
            static contextTypes = {
                store: propTypes.object
            }
            constructor(props, context) {
                super(props)
                console.log('容器组件', context.store);
                //得到sotre
                const { store } = context
                //得到包含所有一般属性的对象
                const stateProps = mapStateToProps(store.getState())
                //将所有的一般属性作为容器组件的状态数据
                this.state = { ...stateProps }
                //得到包含上所有函数属性的对象
                let dispatchProps
                if (typeof mapDispatchToProps === 'function') {
                    dispatchProps = mapDispatchToProps(store.dispatch)
                } else {
                    object.keys(mapDispatchToProps).reduce(() => {
                        const actionCreator = mapDispatchToProps[key]
                        pre[key] = (...args) => store.dispatch(actionCreator(...args))
                    }, {})
                }
                //保存到组件对象上
                this.dispatchProps = dispatchProps
                //绑定store的state的变化监听
                store.subscribe(() => {//store内部的状态数据发生了变化
                    //更新容器组件===》UI组件更新
                    this.setState({ ...mapStateToProps(store.getState()) })

                })
            }


            render() {
                //返回UI组件的标签
                return <UIComponent {...this.state} {...this.dispatchProps} />
            }
        }

    }

}

 

posted @ 2022-05-21 17:05  终究还是避免不了遗憾  阅读(37)  评论(0)    收藏  举报