Redux篇幅
概念介绍:
redux有三个核心概念
1 action
动作的对象
包含2个属性
type:标识属性, 值为字符串, 唯一, 必要属性
data:数据属性, 值类型任意, 可选属性
2 reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的state和action, 产生新的state的纯函数。
3 store
将state、action、reducer联系在一起的对象,
- getState(): 得到state
- dispatch(action): 分发action, 触发reducer调用, 产生新的state
- subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
redux可以帮助我们统一的管理数据的状态,首先安装redux
npm install --save redux
创建store.js文件,引入store构建器
import {createStore,applyMiddleware} from 'redux';
引入reducer
import countRecucer from './count_reducer';
/* 引入redux-thunk支持异步 */
import thunk from 'redux-thunk';
//将store暴露出去
export default createStore(countRecucer,applyMiddleware(thunk));
创建count_reducer.js文件
reducer的本质其实就是一个函数,有两个参数,分别是前一个状态prestate和动作对象action ,初始条件下prestate为undefined,我们可以参数赋值
import {INCREMENT,DEINCREMENT} from './constant';
let initCount = 0;
function countReducer(prestate=initCount,action){
const {type,data} = action;
switch(type){
case INCREMENT:
return prestate+data;
case DEINCREMENT:
return prestate-data;
default:
return prestate;
}
}
export default countReducer;
创建constant.js文件
该模块的给action对象的type属性设置常量值,目的就是统一规范防止写错
export const INCREMENT = 'increment';
export const DEINCREMENT = 'deincrement';
创建count_action.js文件
/* 该组件专门为count组件生成action对象 */
import {INCREMENT,DEINCREMENT} from './constant';
// import store from './store'
export const createIcrementAction = data =>({type:INCREMENT,data});
export const createDeIcrementAction = data =>({type:DEINCREMENT,data});
/* 异步action,就是在函数中去处理action,但store默认处理一般对象,
所以需要引入redux-thunk中间件来支持对函数的处理 */
export const createAsyncIcrementAction = (data,time)=>{
/* 第一个参数是store帮我们添加的,知道需要处理函数,默认传入,避免额外引入store */
return (dispatch)=>{
setTimeout(() => {
dispatch(createIcrementAction(data));
}, time);
}
}
组件中使用redux
import store from './redux/store';
import {createIcrementAction,createDeIcrementAction,createAsyncIcrementAction} from './redux/count_actions'
increment = ()=>{
let value = this.sel.value;
store.dispatch(createIcrementAction(value*1));
}
deincrement = ()=>{
let value = this.sel.value;
store.dispatch(createDeIcrementAction(value*1));
}
incrementIfOdd=()=>{
if(store.getState() % 2 !==0){
let value = this.sel.value;
store.dispatch(createIcrementAction(value*1));
}
}
需要注意的是如果页面响应更新则需要手动在组件中订阅
componentDidMount(){
store.subscribe(()=>{
this.setState({});
})
}
react-redux配合使用
react-Redux将所有组件分成两大类,UI组件和容器组件。它会帮助我们自动将redux数据和前端数据相联,不需要手动订阅就可实现数据双向绑定。
UI组件
- 只负责 UI 的呈现,不带有任何业务逻辑
- 通过props接收数据(一般数据和函数)
- 不使用任何 Redux 的 API
容器组件
- 负责管理数据和业务逻辑,不负责UI的呈现
- 使用 Redux 的 API
使用
index.js文件
provider可以帮助我们一次性的传入store,它会帮助我们把store按需传递给UI组件去使用
import store from './redux/store';
import {Provider} from 'react-redux';
<Provider store={store}>
<App/>
</Provider>
store.js文件
const allReducer = combineReducers({
addcount:countRecucer,
addperson:personReducer
});
组件中使用react-redux
/*引入connect用于连接UI组件和redux,刚开始接收两个函数作为参数,函数返回的都是对象第一个函数可以叫做
mapStateToProps的映射,函数的第一个参数就是state数据,第二个函数可以称作mapDispatchToProps的映射,第一个参数就是dispatch方法
底下我使用了简写的方式。*/
import {connect} from 'react-redux'
export default connect((state)=>({count:state.addcount,personnum:state.addperson}),
{ jia:createIcrementAction,
jian:createDeIcrementAction,
jiaAsync:createAsyncIcrementAction})(Count)
<p>当前求和为{this.props.count}</p>
<h4>当前人数为:{this.props.personnum}</h4>