1.Redux 学习
- Redux核心
- React+ Redux
- Redux 中间件
- 开发Redux 中间件
- Redux综合案例
1.1Redux简介
Redux是javascript状态容器,提供可预测化的状态管理
1.2Redux核心概念和工作流程
- Store :存储状态的容器,JavaScript对象,存所有的状态,
- View :视图,HTML页面
- Actions :对象,描述对状态进行怎样的操作(会根据属性type,来具体的操作)
- Reducers :函数,操作状态并返回新的状态(向store存储状态 )
工作流程所有的状态都存在store中,View不能直接操作store,View必须通过dispatch方法,触发一个Actions,描述下当前的状态要怎么操作,Action会被Reducer接收到,Reducer会根据Actions的type属性值不同,对状态做不同的处理,处理完成之后通过返回值的方式,将状态返回给store,当store中状态更新后,就能通过subscribe知道状态更新了,最后同步视图更新状态。
1.3通过计数器来学习Redux
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="plus">+</button>
<span id="count">0</span>
<button id="minus">-</button>
<script src="redux.min.js"></script>
<script>
// 3. 存储默认状态
var initialState = {
count: 0
}
// 2. 创建 reducer 函数
function reducer (state = initialState, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1}
default:
return state;
}
}
// 1. 创建 store 对象,接收一个reducer函数
var store = Redux.createStore(reducer);
// 4. 定义 action
var increment = { type: 'increment' };
var decrement = { type: 'decrement' };
// 5. 获取按钮 给按钮添加点击事件
document.getElementById('plus').onclick = function () {
// 6. 触发action
store.dispatch(increment);
}
document.getElementById('minus').onclick = function () {
// 6. 触发action
store.dispatch(decrement);
}
// 7. 订阅 store,接收一个函数,可以在函数中获取到更新之后的store中的值
store.subscribe(() => {
// 获取store对象中存储的状态
// console.log(store.getState());
document.getElementById('count').innerHTML = store.getState().count;
})
</script>
</body>
</html>
2.React + Redux
2.1在React中不使用Redux时遇到的问题
在React中组件通信的数据流是单向的,顶层组件可以通过props属性向下层组件传递数据,而下层组件不能向上层组件传递数据,要实现下层组件修改数据,需要上层组件传递修改数据的方法到下层组件,当项目越来越大的时候,组件之间传递数据变得越来越困难。
2.2 在React项目加入Redux好处
使用Redux管理数据,由于Store独立于组件,使得数据管理独立于组件,解决了组件与组件之间传递数据困难的问题
2.3 在React中使用Redux
下载Redux:npm install redux react-redux
2.4 Redux工作流程
- 组件通过dispatch方法触发Action
- Store接收Action并将Action分发给Reducer
- Reducer根据Action类型对状态进行更改并将更改后的状态返回给Store
- 组件订阅了Store中的状态,Store的状态更新会同步到组件
Provider通过provider组件将store放在全局组件可以获取到的地方
import { Provider } from ' react-redux '
// Provider要在项目的最外层调用
const store = createStore(reducer)
<Provider store={store} > <组件></Porvider>
connect作用
- connect会帮助我们订阅Store,当store中的状态发生改变后,会重新渲染组件
- 通过connect可以拿到store的状态,可以通过connect方法把store中的状态映射到组件的props属性中,这样就可以在组件当中通过props属性拿到store的状态了
- 通过connect也可以拿到dispatch方法
function Count ( props ) {
// 可以直接调用props.count ,拿到state中的数据
// 可以直接调用props.dispatch ( { type : ' increment '} )
}
const mapStateToProps = state => ( {
count : state.count
} )
export default connect (mapStateToProps)(Counter);
connect有两个参数
第一个参数:是个函数,函数中有个形参,命名为state
第二个参数:是个函数,要求返回一个对象,在里面定义的方法都会被映射到组件中
function Count ( props ) {
const { count , increment , decrement } = props ;
}
const mapStateToProps = state => ( {
count : state.count
} )
//往下看,还有优化
const mapDispatchToProps = dispatch => ( {
increment ( ) {
dispatch ( type: ' increment ')
},
decrement ( ) {
dispatch ( type: ' decrement ')
},
} )
export default connect (mapStateToProps,mapDispatchToProps)(Counter);
通过bindActionCreators进行优化设计
1. 导入:import { bindActionCreators } from ' redux '
2. 新建actions文件,单独存放action
export const increment = ()=>({ type : ' increment ' })
export const decrement = ()=>({ type : ' decrement ' })
3.引入action文件 :import * as counterActions from ' ../store/actions/counter.action'
4.在bindActionCreators中传入counterActions
const mapDispatchToProps = dispatch => ( {
...bindActionCreators ( counterActions , dispatch ) //第二个参数为dispatch
} )
5.再次优化第四步:
const mapDispatchToProps = dispatch => bindActionCreators ( counterActions , dispatch ) ;