以
TODO
为例分析,实际开发中并不是那么简单,下面的原型只是开发中的一个原型,这个简单的例子,有助于掌握数据处理传递的原则。
# 一、定义constants
这一步不是必须的
/** * 常量统一保存,便于管理 */ export const ADD_TODO = 'ADD_TODO'; export const TOGGLE_TODO = 'TOGGLE_TODO'; export const SET_VISIBILITY = 'SET_VISIBILITY'; //controll todo wheher show or hide export const SHOW_ALL = 'SHOW_ALL'; export const SHOW_ACTIVE = 'SHOW_ACTIVE'; export const SHOW_COMPLETED = 'SHOW_COMPLETED';
@程序员poetry: 代码已经复制到剪贴板
# 二、定义actionCreator
/** * 定义action creator */ import * as actionType from '../constant/index'; let nextTodo = 0; export const addTodo = (text)=>({ type:actionType.ADD_TODO, id:nextTodo++, text }) export const toggleTodo = (id)=>({ type:actionType.TOGGLE_TODO, id }) export const setVisibilityFilter = (filter)=>{ return { type:actionType.SET_VISIBILITY, filter } }
@程序员poetry: 代码已经复制到剪贴板
# 三、定义reducer
拆分reducer
SetVisibility.js
/** * 处理TODO可见与不可见的reducer */ import * as actionType from '../constant/index'; // 初始状态是自己设置的 后面的状态会转化 // 接收当前状态(设置默认的过滤SHOW_ALL,如设置某些选项卡的active一样),和action返回新的state export const visibilityFilter = (state='SHOW_ALL',action)=>{ switch(action.type) { case actionType.SET_VISIBILITY: return action.filter; default: return state; } }
@程序员poetry: 代码已经复制到剪贴板
addTodo.js
/** * 定义处理action的reducers */ import * as actionType from '../constant/index'; //传入当前的状态空数、action export const todos = (state = [],action)=>{ switch(action.type){ // 匹配用户触发的actionType case actionType.ADD_TODO: // 合并上一次的状态和当前的状态 返回todos数组 return [ ...state,//把数组展开合并 { id:action.id, text:action.text, completed:false//用户控制TODO是否处于点击完成的状态 默认false 没点击 } ] // TODO列表来回切换 遍历add_todo返回的数组 通过completed来判断 case actionType.TOGGLE_TODO: return state.map(todo=>(todo.id===action.id)?{...todo,completed:!todo.completed}:todo) default: return state;//匹配不到返回state } }
@程序员poetry: 代码已经复制到剪贴板
合并reducer
/** * 合并reducers */ import { combineReducers } from 'redux' import {todos} from './addTodo'; import {visibilityFilter} from './SetVisibility'; export default combineReducers({ todos, //这些键其实就是被拆分的状态,后面在容器组件中需要通过connect链接 visibilityFilter });
@程序员poetry: 代码已经复制到剪贴板
# 四、定义store
import { applyMiddleware, createStore } from 'redux'; import reducer from '../reducers/index'; import logger from 'redux-logger'; // 创建store 用来存储状态 export const store = createStore( reducer, applyMiddleware(logger) //处理日志中间件 )
@程序员poetry: 代码已经复制到剪贴板
# 五、结合react-redux
这里忽略展示组件,完成源码看文章结尾
- 首先我们在
container
组件中处理好之前分解合并的那些reducer
的键,然后在通过connect
链接,传递给展示组件的属性使用
容器组件处理
react-todos/src/container/FilterLink.js
// 处理数组过滤 import { connect } from 'react-redux'; import Link from '../components/Link'; import { setVisibilityFilter } from '../actions/index'; // 这里的ownProps指的是 FilterLink // 这里的state其实就是之前分解的todos,visibilityFilter const mapStateToProps = (state, ownProps) => { return { active:ownProps.filter === state.visibilityFilter } } /** 如果mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数。 */ const mapDispatchToProps = (dispatch, ownProps) => ({ // 这里处理对应的事件,传递给展示组件的属性 onClick: () => { dispatch(setVisibilityFilter(ownProps.filter)) } }) export default connect( mapStateToProps, mapDispatchToProps )(Link);
@程序员poetry: 代码已经复制到剪贴板
- 分析
- 这里通过
connect
组件把之前reducer
处理的那些状态链接
- 这里通过
export default combineReducers({ todos, //这些键其实就是被拆分的状态,后面在容器组件中需要通过connect链接 visibilityFilter });
@程序员poetry: 代码已经复制到剪贴板
react-todos/src/container/VisibilityTodoList.js
/** * 处理可见于不可见组件的逻辑 */ import {connect} from 'react-redux'; import TodoList from '../components/TodoList'; import {toggleTodo} from '../actions/index'; import * as actionType from '../constant/index'; console.log(toggleTodo) // todos是返回的数组,filter是过滤的选项如SHOW_ALL SHOW_ACTIVE. const getVisibilityTodos = (todos,filter)=>{ switch(filter) { case actionType.SHOW_ALL: return todos; case actionType.SHOW_ACTIVE: return todos.filter(t => !t.completed); case actionType.SHOW_COMPLETED: return todos.filter(t => t.completed); default: throw new Error('未知的'+filter); } } // 把状态转化为展示组件的属性转递过去 /** * * @param {*} state 也就是 * export default CombineReducers({ Todos, SetVisibility *}); * @param {*} ownProps 返回的容器组件本身的参数 如<Filter name="poetries">此时的ownProps就是name了 */ const mapStateToProps = (state) => { return { todos: getVisibilityTodos(state.todos,state.visibilityFilter), count:state.todos.length } } /** * 如果mapDispatchToProps是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出 */ const mapDispatchToProps = { onTodoClick: toggleTodo } export default connect( mapStateToProps, mapDispatchToProps )(TodoList)
<@程序员poetry: 代码已经复制到剪贴板
阅读全文
← 浅析中间件 Immutable总结 →