前言
redux一直是初学者比较难理解的一部分。我们经常在项目里面看到react,redux, react-redux,那么这三者之间有什么联系呢?
- react: 实现ui的一个框架,负责组件ui的渲染。
- redux: 数据管理中心。
- react-redux: 连接组件和数据中心。
所以,其实react和redux没有任何关系。redux只是管理数据的,不关心ui渲染。因此,我们平常也经常看到react + mobx的组合。
数据驱动
我们远古时期用到的JQuery,改变界面必须通过获取dom来操作,无疑是很麻烦的,虽然后面出现一些动态模板,但是这样我们也是需要重新写一次动态模板,重新生成xml。而现在大家常用的无论是Vue还是React都是所谓的数据驱动的模式,通过改变data或者state来改变view。数据驱动的模式是怎么样的呢?我们用下面这张图来介绍一下:

redux
三个原则
- 唯一数据源
- 数据源只能通过纯函数(reducer)修改
- 数据只读
三大核心
- store

// store/state.js
export default {
pageTitle: '首页', //同步数据
infoList: [] // 异步数据(用异步接口获取)
}
// store/index.js
import { applyMiddleware, createStore } from 'redux'
// 中间件,作用:如果不使用该中间件,当我们dispatch一个action时,需要给dispatch函数传入action对象;但如果我们使用了这个中间件,那么就可以传入一个函数,这个函数接收两个参数:dispatch和getState。这个dispatch可以在将来的异步请求完成后使用,对于异步action很有用
import thunk from 'redux-thunk'
import reducers from './reducers'
const store = createStore(
reducers,
applyMiddleware(thunk)
)
export default store;
store是由redux的createStore(reducer, defaultState)生成的,有三个方法:
getState():用于获取store
dispatch(action): 分发action,唯一改变数据源的方式。
subscribe(listener): 注册监听者。
- reducer

//store/reducers.js
import { combineReducers } from 'redux'
import defaultState from './state'
// 一个reducer就是一个函数
function pageTitle(state=defaultState.pageTitle, action) {
switch(action.type){
case 'SET_PAGE_TITLE':
return action.data
default:
return state
}
}
function infoList(state=defaultState.infoList, action){
switch(action.type){
case 'SET_INFO_LIST':
return action.data
default:
return state
}
}
export default combineReducers({
pageTitle,
infoList
})
reducer是一个纯函数,根据prevState和action,得到新的state。
- action

// store/actions.js
import api from '../axios/index'
export function setPageTitle(data){
return (dispatch, getState) => {
dispatch({
type: 'SET_PAGE_TITLE',
data
})
}
}
export function setInfoList(data){
return (dispatch, getState) => {
// 异步请求
api.$http.getCourse({ status: 'open'})
.then(res => {
dispatch({
type: 'SET_INFO_LIST',
data: res.data
})
})
}
}
action其实就是一个对象,主要的是包含一个type属性,表示要执行的动作。
- store + reducer + action

react-redux
react和redux本身没有关系,是react-redux把它们联系起来。
provider
provider实现store的全局访问。 原理:使用React的context,context可以实现跨组件之间的传递。
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router/index'
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux'
import store from './store/index'
import './index.css';
console.log(store)
ReactDOM.render(
<div className='App'>
<Provider store={store}>
{ Router() }
</Provider>
</div>,
document.getElementById('root')
);
connect
connect是连接react和redux。
//mapStateToProps: 将state映射到组件的props中
const mapStateToProps = state => {
return {
pageTitle: state.pageTitle,
infoList: state.infoList
};
};
// mapDispatchToProps: 将dispatch映射到组件的props中
const mapDispatchToProps = (dispatch, ownProps) => {
return {
setPageTitle(data) {
dispatch(setPageTitle(data));
},
setInfoList(data) {
dispatch(setInfoList(data));
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Course);
以上代码可以看出,connect实际上是一个函数。生成一个与redux store连接的容器组件。
connect(mapStateToProps, mapDispatchToProps)(Course);
mapStateToProps:从redux状态树种提取需要的部分作为props传递给当前的组件。
mapDispatchToProps: 将需要的action作为props传递给当前的组件。

总结
react-redux是连接react(ui渲染)和redux(store数据管理中心)的桥梁,实现统一的数据管理,从而更优雅的实现数据驱动的一种模式。