Redux 是一个状态管理框架,通常与 React 结合使用,来实现 React 的状态集中统一化管理。但是与 Vuex 不同的是,Redux 也可以独立使用。并不专职为 React 服务。而 Vuex 主要是为 Vue 专门制定的状态管理工具。 在使用前执行npm install redux react-redux下载 Redux。
实现一个 todoList (代办事项管理),包含的功能有:
添加待办事项;编辑待办事项状态(将待办事项置为已完成或者未完成);删除待办事项;查询待办事项(按状态已完成/未完成/所有查询)。一共分为三个组件实现该功能。 TodoList.js 为核心组件父组件,提供添加待办事项的方法。 TodoItem.js 为任务项组件,渲染任务项视图,提供修改待办事项状态及删除任务的方法。 FilterItem.js 为过滤器组件,渲染过滤项视图。提供筛选待办事项的方法。
action 定义用户行为类型以及该行为所需要的参数。在整个 todolist 程序中,抽象出来的用户行为有:用户添加待办事项、用户改变待办事项状态、用户删除待办事项、用户筛选待办事项。
let count = 0; let actions = { //添加任务 addTodo: (text)=>{ return {type: 'add', payload:{text:text,id:++count,done:false}}; }, //删除任务 delTodo: (index)=>{ return {type: 'del', index}; }, //修改任务状态 changeStatus:(item)=>{ return {type: 'change', item}; }, //过滤任务列表 onFilter:(flag)=>{ return {type: 'filter', flag}; } }; export default actions;reduce 表示根据用户行为,响应不同的状态,然后根据状态更新视图。在整个 todolist 程序中,抽象出来的响应状态有:
新增/删除/更改代办事项之后更新待办事项列表,定义 todosReducers; const todosReducer = (state = [],action)=>{ switch (action.type) { case 'add': state = [...state, action.payload]; return [...state]; case 'del': state.splice(action.index,1); return [...state]; case 'change': action.item.done = !action.item.done; return [...state]; default: return state; } }; export default todosReducer; 根据用户的筛选条件查询出符合条件的待办事项列表,定义 filterReducers。 const filterReducer = (state ="all", action)=>{ switch (action.type) { case 'filter': if(action.flag == 'all'){ state = 'all'; }; if(action.flag == 'completed'){ state = true; }; if(action.flag == 'uncompleted'){ state = false; }; return state; default: return state; } }; export default filterReducer;通过 combineReducers 方法将单个的 Reducer 整合到一起,定义allReducers。
import {combineReducers} from 'redux'; import filterReducer from './filterReducer'; import todosReducer from './todosReducer'; const allReducers = combineReducers({filter:filterReducer,todos:todosReducer}); export default allReducers;store 是储存状态的仓库,所有的 state ,reduce ,跟 redux 相关的 API 等都是储存在 store 中。
import {createStore} from 'redux'; import allReducers from './allReducers'; let store = createStore(allReducers); export default store;TodoList.js
import React from 'react'; import TodoItem from './component/TodoItem'; import Filter from './component/FilterItem'; import {connect} from 'react-redux'; import actions from './store/actions'; class TodoList extends React.Component { constructor(props) { super(props); this.status =[ {label:"所有",flag:"all"}, {label:"已完成",flag:"completed"}, {label:"未完成",flag:"uncompleted"}, ] } add(){ var value = this.refs.input.value; const {addTodo} = this.props; addTodo(value); } render() { const {todos} = this.props; return <div> <input type="text" ref="input"/><button onClick={()=>this.add()}>添加任务</button> {todos.map((item,index)=>{ return <TodoItem item={item} key={index} index={index} /> })} <div className="list-mt-20"> {this.status.map((item,index)=>{ return <Filter item={item} key={index} /> })} </div> </div> } } const mapStateToProps = (state)=>{ return{ todos:state.todos }; }; const mapDispatchToProps = (dispatch)=>{ return { addTodo:(val)=>dispatch(actions.addTodo(val)) } }; export default connect(mapStateToProps,mapDispatchToProps)(TodoList); TodoItem.js 为任务项组件,渲染单条任务项视图,提供修改待办事项状态及删除任务的方法。TodoItem.js
import React from 'react'; import '../index.css'; import {connect} from 'react-redux'; import actions from '../store/actions'; class TodoItem extends React.Component { constructor(props) { super(props); } del(index){ const {delTodo} = this.props; delTodo(index); } changeStatus(item){ const {changeStatus} = this.props; changeStatus(item); } render() { const {item,index,filter} = this.props; return( <div>{filter == 'all'?<div><span className={item && item.done?'list-line':''} onClick={() => this.changeStatus(item)}>{item.text}</span> <button onClick={() => this.del(index)}>删除</button> </div>:(filter == item.done?<div><span className={item && item.done?'list-line':''} onClick={() => this.changeStatus(index)}>{item.text}</span> <button onClick={() => this.del(index)}>删除</button> </div>:null)} </div> ) } } const mapStateToProps = (state)=>{ return{ filter:state.filter, todos:state.todos, }; }; const mapDispatchToProps = (dispatch)=>{ return { delTodo:(index)=>dispatch(actions.delTodo(index)), changeStatus:(item)=>dispatch(actions.changeStatus(item)), } }; export default connect(mapStateToProps,mapDispatchToProps)(TodoItem); FilterItem.js 为过滤器组件,渲染过滤项视图。提供筛选待办事项的方法。FilterItem.js
import React from 'react'; import '../index.css'; import {connect} from 'react-redux'; import actions from '../store/actions'; class Filter extends React.Component { constructor(props) { super(props); } filter(flag){ const {onFilter} = this.props; if(onFilter){ onFilter(flag); } } render() { const {item} = this.props; return<span className="filter-mr-20" onClick={()=>this.filter(item.flag)}>{item.label}</span> } } const mapStateToProps = (state)=>{ return{ filter:state.filter, }; }; const mapDispatchToProps = (dispatch)=>{ return { onFilter:(flag)=>dispatch(actions.onFilter(flag)) } }; export default connect(mapStateToProps,mapDispatchToProps)(Filter);项目中所用到的 connect 方法来自于 Redux 库。该方法是一个高阶组件,接收当前业务逻辑需要用到的 state 和 props 作为第一阶参数,接收当前业务组件作为第二阶参数。处理之后的结果是将所有的 state 和 props 作为 props 注入到当前业务组件中。