自定义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} /> } } } }