由于前段时间做react的一个框架,顺便用上了react-redux,在这里将自己的理解记录下来,给自己增加些印象,顺便希望能帮助一些使用react-redux的萌新们。
网上已有大堆资料介绍react-redux,它是redux和react结合的一个框架,我们可以说是用来专门管理自己数据业务(或逻辑状态)的一个框架。所以在这里我们首先过一遍redux是什么?
redux
redux就是用来统一管理项目中的状态(state)。state它可以是前后端的各种数据,也可以是UI上的一些信息。简单点,它就是个对象,包含了项目中可能用于改变的一些信息。
redux重要关注的几点:Actions,Reducers,Store,下面就分别来看看吧。
1、Actions:
function changeTable(index) {
return { type: "channgTable", data:index }
}
以上例子就是一个action,我们不用纠结它定义个一个函数形式还是其它,最终它就是一个对象。包含type、data或者还有其他元素的对象。
action就是用来告诉我们的状态管理器需要做什么样的一种操作。拿以上例子来说,就是为了做一个切换table的操作,那么我就定义了这么一个action。data就是你做这个操作需要处理的一些数据等。
2、Reducers :
const reducer = function(state={"tableIndex":0}, action={}) {
switch(action.type){
//当发出type为changeTable的action对state的操作
case "changeTable":
let backup = state;
backup["tableIndex"] = action.data;
return Object.assign({}, state,backup);
default :
return Object.assign({}, state);
}
}
以上例子就是一个reducer,它是一个会对不同action做出不同操作的函数。
如当我发出切换table的action时,就是把我们之前定义action的data传递给state下的tableIndex变量,用来告诉state,我要切换table的序号。
在没有任何操作情况下,我们返回初始的state。
我们不直接去改变state的值,而是返回一个新的对象,保持state的唯一性。缓存可以在这里做,后面会有叙述
3、Store:
var store = createStore(reducer);
这就是Store了,用来管理state的单一对象。其中有三个方法:
- store.getState():获取state,如上,经过reducer已经返回了一个新的state,那么就可以用该函数获取;
- store.dispatch(action):发出操作,更新state。action内有操作的类型,就可以出发不同的对state的更新;
- store.subscribe(listener):监听变化,当state发生更新时,就可以在这个函数的回调中监听。
上述为基本redux的用法和含义,发出的操作也是同步的,如要更深入了解异步操作和对state更合理的逻辑管理,可以查看Middleware、combineReducers函数等,本文不再详述。
react-redux
讲完了基本的redux,那么理解和react结合就简单的多了。
在使用react-redux之前,别忘了下载该模块。
react-redux在redux的基础上,就关注两点:Provider和connect。
1、Provider:
<Provider store={store}>
<Router ref="router" history={hashHistory}>
<Route path='/' component={Index}>
<IndexRoute component={MainPage}></IndexRoute>
</Route>
</Router>
</Provider>
Provider就是把我们用rudux创建的store传递到内部的其他组件。让内部组件可以享有这个store并提供对state的更新。
2、connect:
export default connect(mapStateToProps,mapDispatchToProps)(MainPage);
connect()一共有四个参数,但我这里只说基本的两个,mapStateToProps和mapDispatchToProps。
-
mapStateToProps:简单来说,就是把状态绑定到组件的属性当中。我们定义的state对象有哪些属性,在我们组件的props都可以查阅和获取。
const mapStateToProps = (state, ownProps) => { return {tableIndex:state.tableIndex} }
在props中,我们就看到了我们绑定的状态。
它的初值就是reducer默认返回state中的值。
-
mapDispatchToProps:在redux中介绍过,用store.dispatch(action)来发出操作,那么我们同样可以把这个方法封装起来,即绑定到我们的方法中。
const mapDispatchToProps = (dispatch, ownProps) => { return { changeActive:(args)=>dispatch({type:"changeTable",data:args}) } }
可以看到,这个方法return的就是一个dispatch函数,将该方法绑定到属性上,我们同样可以在props查看和调用。
这样,我们只要在组件中调用该属性中的方法,就可以发出一个特定的action,触发reducer对state进行更新。这里的reducer就是之前在redux中定义的reducer。
这时候state如果发生更新,因为我们已经把state也绑定到props中,那么会把这些新的props重新传递下去,组件会进行更新渲染,达到我们需要的目的。
如果需要缓存怎么办?
还记得我们定义的reducer么。我们只需要将最新的状态存起来(无论是sessionStorage、数据库还是其它),然后默认的state去取缓存过的状态进行初始化渲染即可。
const reducer = function(state={"tableIndex":0}, action={}) {
switch(action.type){
//当发出type为changeTable的action对state的操作
case "changeTable":
let backup = state;
backup["tableIndex"] = action.data;
//定义新的state,用于存储
let newState = Object.assign({}, state,backup);
sessionStorage.setItem("state",JSON.stringify(newState));
return newState;
default :
if(sessionStorage.getItem("state")){
//获取缓存过的state
return Object.assign({},JSON.parse(sessionStorage.getItem("state")));
}else{
return Object.assign({}, state);
}
}
}
其实react-redux中还有许多可用配置的参数和方法。越是复杂的项目,用起来会越清晰。本文只是一些基本用法的梳理,更深的了解可访问:https://github.com/reactjs/react-redux 等其他在线资料。