关于redux的介绍推荐去看阮一峰老师的系列文章,但是我这里要先对redux的store和state做一些额外的说明
首先 对于单页应用程序来说全局只有一个store,state当然也只有一个,如果是多页应用,一般每一页对于一个store和一个state,当然,我这里的页是指入口。
下面将说明项目里如何使用react redux react-redux
说明,为什么要同时使用react-redex 因为它能简化你的操作,并且对合理和规范有一定的强制作用
如果要使用这三个东西会涉及到 action component container reducer store dispatch connect
整个流程是这样的
1 我们给 component组件 传入一个函数,假如这个函数是在用户的点击事件中出发的
2 当用户 点击的时候会触发这个函数 在这个函数里 会调用dispatch发送一个action
3 你定义的reduer函数会根据 发送的那个action来计算点击事件对应的state
4 这个全局的state变化后会更新对应的组件 这个对应的组件就是导致dispatch(action)的那个组件也就是你注册点击事件的那个组件所对应的容器包裹着的组件会整体被更新,也 就是说这个容器包裹的组件关心当前这种结构的state,其它的容器包裹的组件是不会被更新的
代码实践及详细说明
假如我们已经有了一个组件 MyClickComponent 我们需要用一个容器去包裹它,并且给它传入我们的那个在点击时会调用并且发送action的方法
1 这里是container 文件
import { bindActionCreators } from 'redux' import { connect } from 'react-redux' /*通过定义这个方法容器组件会将state的成员传递给 MyClickComponent 可以在MyClickComponent中通过 this.props.info 引用到*/ function mapStateToProps(state) { return { info: state.info } }
在这里我们要将那个点击时的回调函数通过容器传递给 MyClickComponent
这个子组件由于我们用了react-redux 所以这个容器我们不会去显示的像定
义组件那样去定义,我们是通过react-redux 的connect来生成的
这里的callbackList 是一个数组 这个数组里的方法是我们要传递给子组件的
并且没一个方法里面都会调用dispatch来发送 action 这些回调方法我们在组
件中通过 this.props都可以引用到,
然后将它们注册到点击事件,鼠标事件,键盘事件等等的回调中去,这样用户
的操作就会发送一个action导致state更新,回过头来刷新组件我能应当明白
mapStateToProps和mapDispatchToProps是在容器中调用的所有容器会将全局
的state和dispatch传递给这两个方法 至于怎么传 你不需要关心,你只需要
关心怎么用
我们看到有个 bindActionCreators ,这个方法接收两个参数,
一个是装了我们要传递给组件的方法的数组,
一个是dispatch 通过调用这个方法到底做了什么事
这个函数会遍历callbackList 将 它里面的每一个函数 例如 有个click
click=dispatch(click.apply(undefined,arguments)最终生成了包装后的click 所有的函数都会被包装
这里我把第一个参数叫做callbackList,很多人喜欢叫做actionCreators 从表面意思来看好像这个函数创建了
action 没错,我们刚开始就说了,在那个回调函数中会调用 dispach(action) 那这个action是哪里来的如何创建的呢
function mapDispatchToProps(dispatch) { return bindActionCreators(callbackList,dispatch) }
创建了我们一直在说的那个容器 第二个框号里的MyClickComponent 是我们被包裹的那个组件
const Container = connect(mapStateToProps,mapDispatchToProps)(MyClickComponent) export Container
2 这里是action 文件
export const UPDATE='UPDATE' function actionCreater(info) { //return的那个对象就是我们的action return { type: UPDATE,info: info } } export function click() { return (dispatch,getState) => { setTimeout(() => { //这里可以向后台去请求需要的 info 数据 //我用setTimeout模拟请求到的数据用来做action的最重要的一部分数据 //这里的info我们可以在组件中通过this.props.info得到 //由此就能明白为什么这个函数也叫actionCreator因为它确实间接的创建了action dispatch(actionCreater(info)) },20) } }
3 这里是reducer文件
//payload 是我们用来生成state的数据 //payload 可以是对应函数,任意你想要的东西 function clickReducer(payload = 'click',action) { switch (action.type) { case UPDATE: return action.info default: return payload } } //由于可以有多个reducer 所以 用combineReducers //注意这里决定了你最终的state的结构 例如 // const rootReducer = combineReducers({ // info:clickReducer,// info2:reducer2 // }) // 对应的 state { // info:clickReducer,// info2:reducer2 // } // const rootReducer = combineReducers({ info:clickReducer }) export default rootReducer //整个应用只有一个reducer 包含了所有的产生state的逻辑
4 这里是 store 文件
export function createStore(initialState) { const store = applyMiddleware(thunk)(createStore)(rootReducer,initialState) return store }
applyMiddleware有三个框号就是柯里化,好高端 就是先调用applyMiddleware(thunk)返回一个函数
这个函数需要 createStore 参数 然后又返回一个函数又需要 initialState参数
这里只是倒出了一个创建store的方法,并没有创建store
5 这里是 entry文件
import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' const store = createStore() render( <Provider store={store}> <Container/> </Provider>,document.getElementById('root') )
这样整个流程就结束,没错就这么简单,这样我们就可以在组件MyClickComponent中随意的注册click事件
并且随意的使用 info ,一旦注册了click,只要用户有相应的操作就会更新state,同时你会得到新的info
值,同时会走一个react 存在的生命周期,有必要的时候会刷新页面
接下来我还会有几篇关于react技术栈的文章
下一次 详细分析 combineReducers connect applyMiddleware bindActionCreators compose这几个函数的原理,有需要的同志关注