自定义redux库
redux语法功能分析
- redux 库向外暴露下面几个函数
- createStore(): 接收的参数为 reducer 函数, 返回为 store 对象
- combineReducers(): 接收包含 n 个 reducer 方法的对象, 返回一个新的 reducer 函数
- store 对象的内部结构
- getState(): 返回值为内部保存的 state 数据
- dispatch(): 参数为 action 对象
- subscribe(): 参数为监听内部 state 更新的回调函数
实现createStore()
实现createStore()的功能
/**
* redux库主模块
* 1. redux 库向外暴露下面几个函数
- createStore(): 接收的参数为 reducer 函数, 返回为 store 对象
- combineReducers(): 接收包含 n 个 reducer 方法的对象, 返回一个新的 reducer 函数
2. store 对象的内部结构
- getState(): 返回值为内部保存的 state 数据
- dispatch(): 参数为 action 对象
- subscribe(): 参数为监听内部 state 更新的回调函数
*/
/**
*
* 根据指定的reducer函数创建一个store对象
*/
export function createStore(reducer) { //接收一个reducer函数
//用来存储内部状态数据的变量,初始值为调用reducer函数返回的结果(外部指定的默认值)
let state = reducer(undefined, { type: '@@redux/init' })
//用来存储监听state更新回调函数的数组容器
const listeners = []
/**
* 返回当前内部的state数据
*/
function getState() {
return state
}
/**
* 分发action
* 1.触发reducer调用,得到新的state
* 2.保存新的state
* 3.调用所有已存在的监视回调
*
*/
function dispatch(action) {
// 1.触发reducer调用,得到新的state
const newState = reducer(state, action)
// 2.保存新的state
state = newState
// 3.调用所有已存在的监视回调
listeners.forEach(listener => listener())
}
/**
* 绑定内部state改变的监听回调
* 可以给一个stort绑定多个监听
*/
function subscribe(listener) {
//保存到缓存Listener的容器数组中
listeners.push(listener)
console.log(listeners)
console.log('触发subscribe')
}
//返回store对象
return {
getState,
dispatch,
subscribe
}
}
/**
*
* 整合传入参数对象中的多个reducer函数,返回一个新的reducer
* 新的reducer管理的总状态:{r1:state1,r2:state2}
*/
export function combineReducers(reducers) {
return (state, action) => {
}
}
实现combineReducers
/**
*
* 整合传入参数对象中的多个reducer函数,返回一个新的reducer
* 新的reducer管理的总状态:{r1:state1,r2:state2}
* reuscers的结构:
* {
* count: (state=2,action) => 3
* user: (state = {}, action) => {}
* }
* 要得到的总状态的结构
* {
* count:count(state.count,action),
* user:user(state.user,action)
* }
*/
// const obj = {
// count: (state = 2, action) => 3,
// user: (state = {}, action) => { }
// }
/**
* forEach版本
*/
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
}
}
/**
* reduce版本
*/
// export function combineReducers(reducers) {
// //返回一个新的总reducer函数
// //state:总状态
// return (state = {}, action) => {
// //执行reducers中每个reducer函数得到一个新的子状态,并封装一个对象容器
// const newState = Object.keys(reducers).reduce((preState, key) => {
// preState[key] = reducers[key](state[key], action)
// return preState
// }, {})
// return newState
// }
// }
//简洁版本
export function combineReducers(reducers) {
return (state = {}, action) => {
return Object.keys(reducers).reduce((pre, key) => {
pre[key] = reducers[key](state[key], action)
return pre
}, {})
}
}
自定义redux-react
1.react-redux 向外暴露了 2 个 API
-
Provider 组件类
-
connect 函数
2.Provider 组件
-
接收 store 属性
-
让所有容器组件都可以看到 store, 从而通过 store 读取/更新状态
3.connect 函数
接收 2 个参数: mapStateToProps 和 mapDispatchToProps
mapStateToProps: 为一个函数, 用来指定向 UI 组件传递哪些一般属性
mapDispatchToProps: 为一个函数或对象, 用来指定向 UI 组件传递哪些函数属性
connect()执行的返回值为一个高阶组件: 包装 UI 组件, 返回一个新的容器组件
容器组件会向 UI 传入前面指定的一般/函数类型属性
代码
/**
* react-redux库的主模块
* 1) react-redux 向外暴露了 2 个 API a. Provider 组件类 b. connect 函数
* 2) Provider 组件
* 接收 store 属性
* 让所有容器组件都可以看到 store, 从而通过 store 读取/更新状态
* 3) connect 函数
* 接收 2 个参数: mapStateToProps 和 mapDispatchToProps
* mapStateToProps: 为一个函数, 用来指定向 UI 组件传递哪些一般属性
* mapDispatchToProps: 为一个函数或对象, 用来指定向 UI 组件传递哪些函数属性
* connect()执行的返回值为一个高阶组件: 包装 UI 组件, 返回一个新的容器组件
* 容器组件会向 UI 传入前面指定的一般/函数类型属性
*/
import React from 'react'
import PropTypes from 'prop-types'
/**
* 用来向所有容器组件提供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('ContainerComponent', context.store)
//得到store
const { store } = context
//得到包含所有一般属性的对象
const stateProps = mapStateToProps(store.getState()) //并且把state中的数据传递过去
//将所有一般属性作为容器组件的状态数据
this.state = { ...stateProps }
//得到包含所有函数属性的对象
let dispatchProps
//判断传递过来的是否是函数
if (typeof mapDispatchToProps === 'function') {
//函数的情况
dispatchProps = mapDispatchToProps(store.dispatch)//并且把dispatch传递过去
} else { //对象的情况
dispatchProps = Object.keys(mapDispatchToProps).reduce((pre, key) => {
const actionCreator = mapDispatchToProps[key]
pre[key] = (...args) => store.dispatch(actionCreator(...args)) //参数透传
return pre
}, {})
}
//保存到组件上
this.dispatchProps = dispatchProps
//绑定store的state变化的监听
store.subscribe(() => { // store内部的状态数据发生了变化
console.log('11')
//更新容器组件 ==> UI更新
this.setState(mapStateToProps(store.getState()))
})
}
render() {
//返回UI组件的标签
return <UIComponent {...this.state} {...this.dispatchProps} />
}
}
}
}
使用:
和react-redux使用方法一样