redux使用方法
在看本文章之前,如果对于redux的原理不太熟悉,可以先观看胡子大哈的React小书.
1.实现Reducer
Reducer是生成store的方法createStore的参数,Reducer是一个方法,它接收两个参数state和action
state即当前组件间共享的数据,action即action = {动作类别, 动作参数}
Reducer方法内部描述了怎样依据action去改变state
createStore是一个工厂方法,内里通过返回出去的方法作用于连保持了state(state就是共享数据)的生命
并返回了一个包括三个方法的对象,三个方法分别为getState,subscribe,dispatch
getState即获取当前state也就是共享数据
subscribe接收一个方法为参数,目的是注册这个方法为dispatch调用后的callback方法
dispatch接收一个参数,这个参数是action = {动作类别, 动作参数}
dispatch内部调用了Reducer并在Reducer执行完毕后执行subscribe注册的callback(一般用于更新组件渲染)
//简易版Reducer
const Reducer = (state, action) => {
if (!state) return {
themeColor: 'red'
}
switch (action.type) {
case 'CHANGE_COLOR':
return { ...state, themeColor: action.themeColor }
default:
return state
}
}
//简易版createStore(redux已经将createStore封装好,这里只是简易介绍源码
//使用时直接import {createStore} from 'redux' 调用createStore即可,不用自己实现)
function createStore (reducer) {
let state = null
const listeners = []
const subscribe = (listener) => listeners.push(listener)
const getState = () => state
const dispatch = (action) => {
state = reducer(state, action)
listeners.forEach((listener) => listener())
}
dispatch({}) // 初始化 state
return { getState, dispatch, subscribe }
}
2.Reducer传入craeteStore生成store
這個store即使实际context共享的数据,Reducer作为createStore的参数传进去
例如:
//示例createStore
let store = createStore(Reducer);
3.Provider将所有要共享数据的组件共同的父组件包裹起来
并作为含有context的高阶组件,同时将store传入,作为context共享的内容
例如
// 头部引入 Provider
import { Provider } from './react-redux'
// 删除 Index 里面所有关于 context 的代码
class Index extends Component {
render () {
return (
<div>
<Header />
<Content />
</div>
)
}
}
// 把 Provider 作为组件树的根节点
ReactDOM.render(
<Provider store={store}>
<Index />
</Provider>,
document.getElementById('root')
)
//Provider的简易源码,可见,其实redux使用的就是context的原理
export class Provider extends Component {
static propTypes = {
store: PropTypes.object,
children: PropTypes.any
}
static childContextTypes = {
store: PropTypes.object
}
getChildContext () {
return {
store: this.props.store
}
}
render () {
return (
<div>{this.props.children}</div>
)
}
}
4.确定state是什么,每个共享数据的组件都要通过mapStateToProps方法将state映射成自己可接收的props对象
例如:
//示例mapStateToProps
mapStateToProps = (state){
return {
props里的内容a: state.a,
props里地内容b: state.b
}
};
5.确定好每个组件各自能够改变state的方法,并通过mapDispatchToProps映射成自己可接收的props对象
例如:
//示例mapDispatchToProps
mapDispatchToProps = (dispatch){
return {
functiona: dispatch({'type': 'a', '操作参数': '操作参数'}),
functionb: dispatch({'type': 'b', '操作参数': '操作参数'}),
}
}
6.每个组件分别将4、5两步生成的映射方法和组件本身传入connect方法,并返回新的组件
这个新的组件就是被connect高阶组件加工过后的作为context child的组件
他们将与Provider包裹后的组件共享store
例如:
加工后的组件 = connect(mapStateToProps, mapDispatchToProps)(加工前的组件)
//简易版connect
export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
class Connect extends Component {
static contextTypes = {
store: PropTypes.object
}
constructor () {
super()
this.state = {
allProps: {}
}
}
componentWillMount () {
const { store } = this.context
this._updateProps()
store.subscribe(() => this._updateProps())
}
_updateProps () {
const { store } = this.context
let stateProps = mapStateToProps
? mapStateToProps(store.getState(), this.props)
: {} // 防止 mapStateToProps 没有传入
let dispatchProps = mapDispatchToProps
? mapDispatchToProps(store.dispatch, this.props)
: {} // 防止 mapDispatchToProps 没有传入
this.setState({
allProps: {
...stateProps,
...dispatchProps,
...this.props
}
})
}
render () {
return <WrappedComponent {...this.state.allProps} />
}
}
return Connect
}
7.redux的基本前置要求已经做好
之后只要各个组件调用mapDispatchToProps中描述的那些方法
即可通过类似与广播的方式通知给所有共享这个store的组件:'state中的某项内容变化了'
部分原理及代码参考自胡子大哈的React小书.