解析react-redux官方案例todo
来源:互联网 发布:淘宝违规申诉入口 编辑:程序博客网 时间:2024/06/05 23:47
我相信很多小伙伴在学习
react-redux
都会涉及到一个todo
的官方案例,不过刚刚开始接触的人可能看十几次都没感觉,现在我本人对它的总结下
一、项目的构建
- 1、本项目我使用前端脚手架
yeoman
构建参考 2、创建一个
todo
项目yo react-webpack
3、安装别的依赖包
npm install redux --savenpm install react-redux --savenpm install redux-thunk --save
4、把刚刚构建的项目运行
npm run serve
5、在浏览器上访问
localhost:8000
二、运行后项目效果图
三、项目组件拆分
- 1、上面输入框与添加按钮拆分为一个组件
AddTodo
- 2、中间显示的拆分一个组件
TodoList
- 3、底部分类拆分一个组件
Link
四、todo
项目的开发
1、项目结构(关心我圈住的就可以)
- 2、根据
redux
构建项目的方式创建几个文件夹如不清楚请参考 3、开发流程(一般开发流程)
五、AddTodo
组件的开发
1、创建
action
(如果项目大,可以一个组件写一个action.js
)/** * 定义todo项目的action */'use strict';let nextTodo = 0;// 一般外面需要使用的会定义常量export const ADD_TODO = 'ADD_TODO';export const TOGGLE_TODO = 'TOGGLE_TODO';// 定义一个添加的actionexport const addTodo = (text) => ({ type: ADD_TODO, id: nextTodo++, text});// 定义一个切换的actionexport const toggleTodo = (id) => ({ type: TOGGLE_TODO, id})
2、
AddTodo
组件的reducer
的书写项目需要可以一个组件写一个
reducer.js
然后用combineReducers
合并在一起import { combineReducers } from 'redux';import { ADD_TODO, TOGGLE_TODO} from './../actions/index';const todos = (state = [], action) => { switch (action.type) { case ADD_TODO: return [ ...state, { id: action.id, text: action.text, completed: false } ]; case TOGGLE_TODO: // 定义切换的,如果当前点击的id等于传递进来的id就改变状态,否则就不边 return state.map(todo => { if (todo.id === action.id) { return { ...todo, completed: !todo.completed } } else { return todo; } }) default: return state; }}
3、书写展示组件
...render() { // console.log(this.props); return ( <div> <input type="text" placeholder="请输入内容" ref="myinput"/> <input type="button" value="添加" onClick={this.addTodo} /> </div> )}...
4、容器组件(如果对块还有不清楚请参考)
'use strict'/** * 定义AddTodo的容器组件 */import {connect} from 'react-redux';import AddTodo from './../components/AddTodo';// 这样全部的导入的就有点浪费,在AddTodo中只用了一个addTodo方法// import * as ActionCreators from './../actions/index';import {addTodo} from './../actions';export default connect( state=>({todos:state.todos}), // ActionCreators dispatch =>({ addTodo:(text)=>dispatch(addTodo(text)) }))(AddTodo);
5、容器组件传递了
todos
和addTodo
到展示组件,再看展示组件的完整代码/** * AddTodo展示组件 */'use strict'import React, { Component } from 'react';export default class AddTodo extends Component { constructor(props) { super(props); this.addTodo = this.addTodo.bind(this); } render() { // console.log(this.props); return ( <div> <input type="text" placeholder="请输入内容" ref="myinput"/> <input type="button" value="添加" onClick={this.addTodo} /> </div> ) } // 增加的todo的方法 addTodo() { const { addTodo } = this.props; // 获取到input的dom节点 let myinputDom = this.refs.myinput; // 发送完成后就清空输入框 addTodo(myinputDom.value); myinputDom.value = ''; }}// 约束数据类型AddTodo.protoTypes = { addTodo: React.PropTypes.func.isRequired}
6、组装到项目中试跑(本项目中创建了一个入口的
App.js
来统一管理)import 'core-js/fn/object/assign';import React from 'react';import ReactDOM from 'react-dom';import {createStore,applyMiddleware} from 'redux';import thunk from 'redux-thunk';import {Provider} from 'react-redux';import todoApp from './reducers/index';import App from './components/App';let store = createStore(todoApp,applyMiddleware(thunk));// Render the main component into the domReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('app'));
/** * 主文件入口 */'use strict'import React, { Component } from 'react';import AddTodoConnect from './../containers/AddTodoConnect';export default class App extends Component { constructor(props){ super(props); } render() { return ( <div> <AddTodoConnect/> </div> ) }}
六、显示添加的todo
组件
1、展示组件(就是接受
props
数组便利出来)/** * todo的展示组件 */'use strict'import React, { Component } from 'react';// 引入样式require('styles/todolist.css');export default class TodoList extends Component { constructor(props) { super(props); } render() { const { todos, toggleTodo } = this.props; return ( <ul> { todos.map(todo => ( // 注意这个地方不能直接写onClik = {toggleTodo},这样的意思是立即执行 //<li key={todo.id} onClick={()=>toggleTodo(todo.id)} style={{ //textDecoration: todo.completed ? 'line-through' : 'none', //color: todo.completed ? 'red' : 'black' //}}>{todo.text}</li> <li key={todo.id} onClick={() => toggleTodo(todo.id)} className={todo.completed ? 'list-select' : 'list'}>{todo.text}</li> )) } </ul> ) }}// 约束数据类型TodoList.protoTypes = { todos: React.PropTypes.object.isRequired, toggleTodo:React.PropTypes.func.isRequired}
2、对应的容器组件
/** * TodoList的容器组件 */'use strict'import { connect } from 'react-redux';import TodoList from './../components/TodoList';import { toggleTodo } from './../actions/index';export default connect( state => ({ todos: state.todos}), dispatch => ({ toggleTodo: (id) => dispatch(toggleTodo(id)) }))(TodoList);
3、组装到
App.js
中
七、底部的组件
1、在
action
里面添加...export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';export const SHOW_ALL = 'SHOW_ALL';// 定义一个是否显示的action,每次发送出去的的type是一样的export const setVisibilityFilter = (filter) => ({ type: SET_VISIBILITY_FILTER, filter})
2、在
reducer
里面添加// 定义一个底部选择的reducerconst visibilityFilter = (state = SHOW_ALL,action) => { switch(action.type){ case SET_VISIBILITY_FILTER: return action.filter default: return state }}// 利用redux里面的combineReducers合并所有的reducerconst todoApp = combineReducers({ todos, visibilityFilter})// 默认导出export default todoApp;
3、定义展示组件
/** * 定义一个底部现在的展示组件 */'use strict'import React, { Component } from 'react'// 引入样式require('styles/link.css');export default class Link extends Component { constructor(props) { super(props); } render() { const { active, children, onClick } = this.props; if (active) { return <span>{children}</span> } else { return ( <a href="javascript:void(0)" onClick={()=>onClick()}>{children}</a> ) } }}
4、定义容器组件(关于
ownProps
参考)/** * 定义Link的容器组件 */import { connect } from 'react-redux';import Link from './../components/Link.js';import { setVisibilityFilter } from './../actions/index';const mapStateToProps = function(state, ownProps){ console.log('ownProps--->',ownProps); return { active: ownProps.filter === state.visibilityFilter }}const mapDispatchToProps = (dispatch, ownProps) => ({ onClick: () => { dispatch(setVisibilityFilter(ownProps.filter)) }})/**下面这样也可以 * (state, ownProps) => ({ active: ownProps.filter === state.visibilityFilter }), (dispatch,ownProps) => ({ onClick: () => dispatch(setVisibilityFilter(ownProps.filter)) }) */export default connect( mapStateToProps, mapDispatchToProps)(Link);
5、修改之前显示的
todo
组件(容器组件)** * 定义一个过滤的方法 */const getVisibleTodos = (todos, filter) => { switch(filter){ case 'SHOW_ALL': return todos; case 'SHOW_ACTIVE': //未完成 return todos.filter(todo => !todo.completed); case 'SHOW_COMPLETED': // 已完成 return todos.filter(todo => todo.completed); default: return todos; }}export default connect( // 传递到展示组件的数据过滤了 state => ({ todos: getVisibleTodos(state.todos,state.visibilityFilter)}), dispatch => ({ toggleTodo: (id) => dispatch(toggleTodo(id)) }))(TodoList);
八、demo下载地址
阅读全文
0 0
- 解析react-redux官方案例todo
- Redux入门案例todo
- React 6 模块化React和Redux应用--Todo应用
- react-redux连接react与redux入门案例
- React实战-通过ToDo源码分析Redux的数据模型设计
- react+redux+react-redux
- redux 及 react-redux基本用法及源码解析
- react-redux部分关键源码解析
- react-redux中的connect方法解析
- react-redux连接react与redux入门案例[分目录结构]
- redux react-redux
- Redux(三: React-Redux)
- react-redux
- React + Redux
- React&Redux
- react-redux
- React Redux
- react-redux
- 学生代码笔记- 0.1
- 一篇实用的Latex的入门教程
- Class对象
- for循环中条件的三种写法
- Network In Network论文笔记
- 解析react-redux官方案例todo
- Java IO流(三)-- 文件的处理与随机访问
- grep指令详解
- Eclipse上Git使用基本方法
- Network
- 已知先序中序求后序 C实现(分治法)
- 深入了解计算机系统 读完
- 用maven创建项目出现错误Cannot change version of project facet Dynamic Web Module to 3.0
- 51. N-Queens