Redux是一个用来管理管理数据状态和UI状态的JavaScript应用工具。随着JavaScript单页应用(SPA)开发日趋复杂,JavaScript需要管理比任何时候都要多的state(状态),Redux就是降低管理难度的。(Redux支持React,Angular、jQuery甚至纯JavaScript)
Redux如何简化状态管理的
可以看出,如果不用Redux,要传递state是非常麻烦的。Redux中,可以把数据先放在数据仓库(store-公用状态存储空间)中,这里可以统一管理状态,然后哪个组件用到了,就去store中查找状态。如果图中的紫色组件想改变状态时,只需要改变store中的状态,然后其他组件就会跟着自动进行改变。
Redux流程图:
图中可以看出:
- 首先,用户(通过view)发出action,发出方式就用到了dispatch方法。
- 然后,Store自动调用reducer,并传入两个参数:当前state和收到的action,reducer会返回新的state。
- State一旦有变化,store就会调用监听函数,来更新view。
小例子:用redux实现一个简单的TodoList小案例
1、redux插件的安装
npm install --save redux
安装好redux之后,在src目录下创建一个store文件夹,然后在文件夹下创建一个index.js文件。
import { createStore } from 'redux';
import reducer from './reducer';
const store = createStore({
reducer,
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__()
// redux插件的配置,配置之后可在chrome浏览器中进行Redux调试
})
export default store;
2、reducer (redux中有管理能力的模块)
const defaultState = {
inputValue: '',
list:[
'早8点开晨会,分配今天的代码任务',
'早9点和项目经理开需求沟通会',
'晚5点组织人员进行Review代码',
'晚6点总结今日工作内容',
]
}
export default (state = defaultState, action) => {
// input输入框内容变化
if (action.type === 'changeInput') {
let newState = JSON.parse(JSON.stringify(state)); //深拷贝
newState.inputValue = action.value;
return newState;
}
// 点击增加按钮
if (action.type === 'addItem') {
let newState = JSON.parse(JSON.stringify(state)); //深拷贝
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
// 点击list项删除对应项
if (action.type === 'deleteItem') {
let newState = JSON.parse(JSON.stringify(state)); //深拷贝
newState.list.splice(action.index, 1);
return newState;
}
return state;
}
注意:Reducer里只能接收state,不能改变state,所以每一个对应action中需要对state进行深拷贝
3、TodoList.js文件
import React, { Component } from 'react';
import { Input, Button, List } from 'antd';
import store from './store';
import 'antd/dist/antd.css';
class TodoList from React.Component {
constructor(props) {
super(props);
this.state=store.getState(); // store.getState()方法可以拿到reducer.js中的数据
this.changeInputvalue=this.changeInputvalue.bind(this);
this.storeChange=this.storeChange.bind(this);
this.clickBtn=this.clickBtn.bind(this);
store.subscribe(this.storeChange); //如果想要state的状态发生变化,订阅模式必须写上
}
storeChange(){
this.setState(store.getState());
}
changeInputvalue(e) {
const action = {
type: 'changeInput',
value: e.target.value
}
store.dispatch(action)
}
clickBtn() {
const action = {
type: 'addItem'
}
store.dispatch(action)
}
deleteItem(index) {
const action = {
type: 'deleteItem',
index
}
store.dispatch(action)
}
render () {
return (
<div style={{margin:'10px'}}>
<div>
<Input
placeholder={this.state.inputValue}
style={{width:'250px', marginRight:'10px'}}
onChange={this.changeInputvalue}
value={this.state.inputValue}
/>
<Button type="primary" onClick={this.clickBtn}>增加</Button>
<div style={{margin:'10px',width:'300px'}}>
<List
bordered
dataSource={this.state.list}
renderItem={(item,index) =>
(<List.Item onClick={this.deleteItem.bind(this,index)}>{item} </List.Item>)}
/>
</div>
</div>
</div>
)
}
}
注意:如果想要state的状态发生变化,订阅模式必须写上,在storeChange方法中重新setState获取store中最新的状态
小案例运行图: