概述
我相信很多小伙伴在学习
react-redux
都会涉及到一个todo
的官方案例,不过刚刚开始接触的人可能看十几次都没感觉,现在我本人对它的总结下
一、项目的构建
- 1、本项目我使用前端脚手架
yeoman
构建参考 2、创建一个
todo
项目yo react-webpack
3、安装别的依赖包
npm install redux --save npm install react-redux --save npm 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'; // 定义一个添加的action export const addTodo = (text) => ({ type: ADD_TODO, id: nextTodo++, text }); // 定义一个切换的action export 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 dom ReactDOM.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
里面添加// 定义一个底部选择的reducer const visibilityFilter = (state = SHOW_ALL,action) => { switch(action.type){ case SET_VISIBILITY_FILTER: return action.filter default: return state } } // 利用redux里面的combineReducers合并所有的reducer const 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下载地址
最后
以上就是英勇可乐为你收集整理的解析react-redux官方案例todo的全部内容,希望文章能够帮你解决解析react-redux官方案例todo所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复