React是什么?
redux是一个独立专门用于做状态管理的JS库(不是React插件库),作用:集中式管理react应用中多个组件状态共享的状态
React主要有三个大模块:action Creator、Store、Reducers
接下来主要自己实现一下内容:
1. createStore(reducer) :接收一个reducer函数,返回一个store对象
2. combineReducers(reducers) : 接收一个包含多个reducer函数的对象,返回一个新的reducer函数
3.store 对象
+ getState() : 得到内部管理的state对象
+ dispatch(action): 分发action,会触发reducer调用,返回一个新的状态,调用所有绑定的listener
+ subscribe(listener): 订阅一个state的监视器
createStore的实现
export function createStore(reducer) {
// 内部保存n个listener的数组
const listeners = []
// 内部state
let state
// 第一次调用reducer得到初始状态并保存
state = reducer(state, { type: '@mini-redux' })
// 得到内部管理的state对象
function getState() {
return state
}
function dispatch(action) {
// 调用reducer,得到新的state 并保存
state = reducer(state, action)
// 调用所有listener的监视回调函数
listeners.forEach(listener => listener())
}
// 订阅一个state的监视器
function subscribe(listener) {
listeners.push(listener)
}
return { getState, dispatch, subscribe }
}
conbineReducers的实现:接收一个reducers对象,返回一个新的reducer函数
// 接收一个包含多个reducer函数的对象,返回一个新的reducer函数
export function combineReducers(reducers) {
return function(state = {}, action) {
// 这个函数会传给createStore()
// 依次调用所有的reducer函数,得到n个新的子状态,封装成对象并返回
// 准备一个用来保存所有新状态的容器对象
const newState = {}
// 包含所有reducer函数名的数组: ['count','msgs']
const keys = Object.keys(reducers)
keys.forEach(key => {
// 得到对应的reducer函数
const childReducer = reducers[key]
// 得到对应的子state
const childState = state[key]
// 执行子reducer
const newChildState = childReducer(childState, action)
// 保存到新的总state中
newState[key] = newChildState
})
// 返回总的新state
return newState
}
}
以下是简写
export function combineReducers2(reducers) {
return function(state = {}, action) {
// 这个函数会传给createStore()
// 依次调用所有的reducer函数,得到n个新的子状态,封装成对象并返回
return Object.keys(reducers).reduce((newState, reducerName) => {
newState[reducerName] = reducers[reducerName](state[reducerName], action)
return newState
}, {})
}
}
这样就初步完成了自己的redux,理解上述代码,可以进一步了解redux的底层原理,接下来就是React-redux的实现
React-redux主要是两个模块:Provider组件,connect函数
Provider组件:为所有的容器子组件提供store(注意:这里使用的context语法)
代码实现
const StateContext = React.createContext()
export class Provider extends React.Component {
static propTypes = {
store: propTypes.Object.isRequired
}
// 为子组件提供一个包含store的context
render() {
return (
<StateContext.Provider value={this.props.store}>
{/* 将所有子标签返回 */}
{this.props.children}
</StateContext.Provider>
)
}
}
connect函数:将ui组件包装成一个容器组件
export function connect(mapStateToProps, mapDispatchToProps) {
// 返回一个函数(接收一个组件)
return WrapComponent => {
return class ConnectComponent extends React.Component {
// 声明获取context数据
static contextType = StateContext
constructor(props, context) {
super(props, context)
// 包含一般属性的对象
const stateProps = mapStateToProps(this.context)
// 包含函数属性的对象
const dispatchProps = this.bindActionCreators(mapDispatchToProps)
// 将所有的一般属性都保存到state中
this.state = stateProps
// 将所有的函数属性的对象保存到组件对象中
this.dispatchProps = dispatchProps
}
// 根据mapDispatchToProps 返回一个包含分发action的函数的对象
bindActionCreators = mapDispatchToProps => {
const keys = Object.keys(mapDispatchToProps)
return keys.reduce((preDispatchProps, key) => {
// 添加一个包含dispatch语句的方法
// 透传:将函数接受到的参数,原样传给内部函数调用
preDispatchProps[key] = (...args) => {
// 分发action
this.context.dispatch(mapDispatchToProps[key](...args))
}
return preDispatchProps
}, {})
}
componentDidMount() {
// 订阅监听
this.context.subscribe(function() {
// redux中产生了一个新的state
// 更新当前组件的状态
this.setState(mapStateToProps(this.context.getState()))
})
}
render() {
return <WrapComponent {...this.state} {...this.dispatchProps} />
}
}
}
}