在vue之中有VueX做全局的状态管理,在react之中有两种方案:1. redux; 2. mobx
redux的特点
在使用之前,需要先了解一下redux的特点。
- redux是为了解决页面间数据(state)共享而生的,因此其内部数据应该很容易地被每个页面/组件获取;
- 单一数据源:整个应用的state都存在于一个store(数据仓库)中;
- state是只读的:唯一改变state的方法只能是通过触发(dispatch)action来产生;
- 为了描述action如何改变state,需要reducers函数
简单的redux示例
根据以上特点来编写一个简单的redux来明白其工作流程:以简单的加减为例
//html结构
//注意onclick函数:特点3 通过dispatch action来改变state
<button onclick="store.dispatch({type:'JIAN',n:2})">-</button>
<span id="countDisplay">5</span>
<button onclick="store.dispatch({type:'JIA',n:3})">+</button>
//script
const createStore = (reducers) =>{
// 特点2:单一数据源,只存在于函数内部
let state = null
const Listeners = []
const subscribe = (listener) => Listeners.push(listener)
// 特点3
const dispatch = (action) =>{
// 特点4
state = reducers(state, action)
//模拟渲染视图
Listenrs.forEach(listener=> listener()
}
const getState = () => state
return{
getState,
dispatch,
subscribe
}
}
const countState = {
count: 5
}
//reducer函数,输入state,action,根据action的类型来改变内部的state
const click = (state, action) =>{
if(!state){
return countState
}
switch(action.type){
case 'JIAN':
return{
...state,
count: state.count - action.n
}
case 'JIA':
return {
...state,
count: state.count + action.n
}
default:
return state
}
}
//创建store
const store = createStore(click)
//获取store内部state的数据
const renderCount = () => {
countDisplay.innerHTML = store.getState().count
}
//订阅渲染界面的函数
store.subscribe(renderCount)
以上就上一个简单的redux工作流程:
- reducers负责干活:根据action.type来改变内部state
- dispatch作为中介,当有交互发生的时候,dispatch就派发动作并让reducers开始干活。注意:在这里我们直接写的是store.dispatch({type:'JIAN',n:2}),我们也可以写一个函数,只要它返回的结果是action类型的,如store.dispatch(login(paylaod:any)),方便传参
- getState负责获取state数据,当数据发生改变后界面就开始渲染
flux架构
可以看出redux的工作流程就是依据flux架构来的
redux使用
react-redux, redux-thunk(异步中间件), connected-react-router(路由注入state中)
完整的案例见GitHub:github.com/Simplyme082…
创建三部分文件:
- store.tsx 生成数据仓库
- action文件夹,管理不同组件对应的action
- reducer文件夹,管理不同组件对应的reducer,其中index.tsx管理所有的reducer,并将其合并成一个reducer
项目文件中:
//Login为登录组件
connect(mapStatetoProps, mapDispatchToProps)(Login)
从字面意思上可以看出这是一个State和dispatch与props的mapping关系。
- mapStatetoProps: 这里的State是指redux中的state,而props是当前组件的props。数据是从redux中传入组件的。从下方代码可以看出这里是取出redux中的完整/部分state值存入组件中
//此属性写在组件文件中
const mapStatetoProps = (state: combinedState): usersActionState => {
return state.users
}
- mapDispatchToProps: 这里就是指把dispatch传入当前组件的props中。而在此例中应用了异步数据,因此要使用redux-thunk中间件可以让我们手动决定什么时候调用dispatch函数以达到异步的目的。
//此属性写在action文件夹内对应的文件中
export const mapDispatchToProps=(dispatch:Dispatch)=>({
login(payload:any){
dispatch(startLogin())
request(payload).then(res=>{
dispatch(loginSuccess(res))
}).catch((err:any)=>{
console.log(err)
dispatch(loginFailed())
})
}
})
注:视图的更新react会自动帮我们完成
总结
react-redux的使用还是比较复杂的,因此对于过页面共享数据的情景下才会使用,对于日常一些小项目无需使用如此繁杂的redux。