今天再来一个例子,我们从组件开始。

App.js

 import React, { PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Header from '../components/Header'
import MainSection from '../components/MainSection'
import * as TodoActions from '../actions' const App = ({todos, actions}) => (
<div>
<Header addTodo={actions.addTodo} /> //头部负责添加事项
<MainSection todos={todos} actions={actions} /> //这是2个组件
</div>
) App.propTypes = {
todos: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired //todos是数组 actions是对象
} const mapStateToProps = state => ({
todos: state.todos
}) const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(TodoActions, dispatch)
}) export default connect(
mapStateToProps,
mapDispatchToProps
)(App)

head.js

 import React, { PropTypes, Component } from 'react'
import TodoTextInput from './TodoTextInput' export default class Header extends Component { //es6组建写法
static propTypes = {
addTodo: PropTypes.func.isRequired
} handleSave = text => {
if (text.length !== 0) {
this.props.addTodo(text)
}
} render() {
return (
<header className="header">
<h1>todos</h1>
<TodoTextInput newTodo
onSave={this.handleSave} //添加事项
placeholder="What needs to be done?" />
</header>
)
}
}
TodoTextInput.js
 import React, { Component, PropTypes } from 'react'
import classnames from 'classnames' export default class TodoTextInput extends Component {
static propTypes = {
onSave: PropTypes.func.isRequired,
text: PropTypes.string,
placeholder: PropTypes.string,
editing: PropTypes.bool,
newTodo: PropTypes.bool
} state = {
text: this.props.text || ''
} handleSubmit = e => {
const text = e.target.value.trim()
if (e.which === 13) {
this.props.onSave(text) //保存文本值
if (this.props.newTodo) {
this.setState({ text: '' })
}
}
} handleChange = e => {
this.setState({ text: e.target.value })
} handleBlur = e => {
if (!this.props.newTodo) {
this.props.onSave(e.target.value)
}
} render() {
return (
<input className={
classnames({
edit: this.props.editing,
'new-todo': this.props.newTodo
})}
type="text"
placeholder={this.props.placeholder} //what needs to be done?
autoFocus="true"
value={this.state.text}
onBlur={this.handleBlur}
onChange={this.handleChange} //改变state里面的值
onKeyDown={this.handleSubmit} /> //keycode=13 提交保存
)
}
}

mainSection.js

 import React, { Component, PropTypes } from 'react'
import TodoItem from './TodoItem'
import Footer from './Footer'
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters' //过滤器 const TODO_FILTERS = {
[SHOW_ALL]: () => true,
[SHOW_ACTIVE]: todo => !todo.completed,
[SHOW_COMPLETED]: todo => todo.completed
} export default class MainSection extends Component {
static propTypes = {
todos: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
} state = { filter: SHOW_ALL } handleClearCompleted = () => {
this.props.actions.clearCompleted() //清除完成事项
} handleShow = filter => {
this.setState({ filter }) //根据过滤条件展示
} renderToggleAll(completedCount) {
const { todos, actions } = this.props
if (todos.length > 0) {
return (
<input className="toggle-all"
type="checkbox"
checked={completedCount === todos.length} //是否全部完成
onChange={actions.completeAll} />
)
}
} renderFooter(completedCount) {
const { todos } = this.props
const { filter } = this.state
const activeCount = todos.length - completedCount if (todos.length) {
return (
<Footer completedCount={completedCount}
activeCount={activeCount}
filter={filter}
onClearCompleted={this.handleClearCompleted.bind(this)}
onShow={this.handleShow.bind(this)} />
)
}
} render() {
const { todos, actions } = this.props
const { filter } = this.state const filteredTodos = todos.filter(TODO_FILTERS[filter]) //初始值为showall 展示全部
const completedCount = todos.reduce((count, todo) => //统计已完成事项
todo.completed ? count + 1 : count,
0
) return (
<section className="main">
{this.renderToggleAll(completedCount)}
<ul className="todo-list">
{filteredTodos.map(todo =>
<TodoItem key={todo.id} todo={todo} {...actions} />
)}
</ul>
{this.renderFooter(completedCount)}
</section>
)
}
}

todoItems.js

 import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import TodoTextInput from './TodoTextInput' export default class TodoItem extends Component {
static propTypes = {
todo: PropTypes.object.isRequired,
editTodo: PropTypes.func.isRequired,
deleteTodo: PropTypes.func.isRequired,
completeTodo: PropTypes.func.isRequired
} state = {
editing: false
} handleDoubleClick = () => {
this.setState({ editing: true })
} handleSave = (id, text) => {
if (text.length === 0) {
this.props.deleteTodo(id)
} else {
this.props.editTodo(id, text) //编辑 不存在text则删除该项
}
this.setState({ editing: false })
} render() {
const { todo, completeTodo, deleteTodo } = this.props let element
if (this.state.editing) {
element = (
<TodoTextInput text={todo.text}
editing={this.state.editing}
onSave={(text) => this.handleSave(todo.id, text)} />
)
} else {
element = (
<div className="view">
<input className="toggle"
type="checkbox"
checked={todo.completed}
onChange={() => completeTodo(todo.id)} />
<label onDoubleClick={this.handleDoubleClick}> //双击修改为可编辑状态 会重新渲染
{todo.text}
</label>
<button className="destroy"
onClick={() => deleteTodo(todo.id)} />
</div>
)
} return (
<li className={classnames({
completed: todo.completed,
editing: this.state.editing
})}>
{element}
</li>
)
}
}

footer.js

 import React, { PropTypes, Component } from 'react'
import classnames from 'classnames'
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters' const FILTER_TITLES = {
[SHOW_ALL]: 'All',
[SHOW_ACTIVE]: 'Active',
[SHOW_COMPLETED]: 'Completed'
} export default class Footer extends Component {
static propTypes = {
completedCount: PropTypes.number.isRequired,
activeCount: PropTypes.number.isRequired,
filter: PropTypes.string.isRequired,
onClearCompleted: PropTypes.func.isRequired,
onShow: PropTypes.func.isRequired
} renderTodoCount() {
const { activeCount } = this.props
const itemWord = activeCount === 1 ? 'item' : 'items' //此处语法经典 return (
<span className="todo-count">
<strong>{activeCount || 'No'}</strong> {itemWord} left //有多少未完成事项
</span>
)
} renderFilterLink(filter) {
const title = FILTER_TITLES[filter]
const { filter: selectedFilter, onShow } = this.props return (
<a className={classnames({ selected: filter === selectedFilter })}
style={{ cursor: 'pointer' }}
onClick={() => onShow(filter)}>
{title}
</a>
)
} renderClearButton() {
const { completedCount, onClearCompleted } = this.props
if (completedCount > 0) {
return (
<button className="clear-completed"
onClick={onClearCompleted} >
Clear completed
</button>
)
}
} render() {
return (
<footer className="footer">
{this.renderTodoCount()}
<ul className="filters">
{[ SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED ].map(filter =>
<li key={filter}>
{this.renderFilterLink(filter)} //切换不同的过滤条件
</li>
)}
</ul>
{this.renderClearButton()}
</footer>
)
}
}

好了  这就是组件  比上次有点多  不过当成是训练    最重要的是把握整体结构

indes.js

 import * as types from '../constants/ActionTypes'

 export const addTodo = text => ({ type: types.ADD_TODO, text })
export const deleteTodo = id => ({ type: types.DELETE_TODO, id })
export const editTodo = (id, text) => ({ type: types.EDIT_TODO, id, text }) //这一看就是dispatch的内容
export const completeTodo = id => ({ type: types.COMPLETE_TODO, id })
export const completeAll = () => ({ type: types.COMPLETE_ALL })
export const clearCompleted = () => ({ type: types.CLEAR_COMPLETED })

todo.js

 import { ADD_TODO, DELETE_TODO, EDIT_TODO, COMPLETE_TODO, COMPLETE_ALL, CLEAR_COMPLETED } from '../constants/ActionTypes'

 const initialState = [
{
text: 'Use Redux',
completed: false,
id: 0 //初始化state
}
] export default function todos(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return [
{
id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1, //确定id值
completed: false,
text: action.text
},
...state
] case DELETE_TODO:
return state.filter(todo =>
todo.id !== action.id
) case EDIT_TODO:
return state.map(todo =>
todo.id === action.id?
(...todo,{text:action.text}):
todo
) case COMPLETE_TODO:
return state.map(todo =>
todo.id === action.id ?
{ ...todo, completed: !todo.completed } : //用于切换
todo
) case COMPLETE_ALL:
const areAllMarked = state.every(todo => todo.completed) //全部完成 或全部未完成
return state.map(todo => ({
...todo,
completed: !areAllMarked
})) case CLEAR_COMPLETED:
return state.filter(todo => todo.completed === false) default:
return state
}
}

index.js  整合reducers

 import { combineReducers } from 'redux'
import todos from './todos' const rootReducer = combineReducers({
todos
}) export default rootReducer

好了  代码就这么多  这一次reducers倒不是很复杂  反倒组件有点乱   总之是单向数据流动,根据action的类型做出相应的改变,最后重新render。。。

 

用redux完成事务清单的更多相关文章

  1. 内容提供者 ContentResolver 数据库 示例 -1

    MainActivity public class MainActivity extends ListActivity {     private TextView tv_info;     priv ...

  2. Spring Transaction 使用入门 (转)

    Spring Transaction 使用入门 一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这 ...

  3. Spring Transaction 使用入门

    一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这是第一篇,记录spring Transactio ...

  4. 如何查找SAP的事务代码清单

    SAP系统中,为了省去输入程序名称等繁琐步骤,SAP提供一种命令,称作‘事务代码’,通过执行事务代码达到快速进入相应程序的目的.那么在系统中如何去查找事务代码,事务代码和程序的对应关系如何呢?我们可以 ...

  5. SAP MM事务代码清单

  6. react+redux教程(七)自定义redux中间件

    今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 ...

  7. react+redux教程(四)undo、devtools、router

    上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...

  8. angular开发者吐槽react+redux的复杂:“一个demo证明你的开发效率低下”

    曾经看到一篇文章,写的是jquery开发者吐槽angular的复杂.作为一个angular开发者,我来吐槽一下react+redux的复杂. 例子 为了让大家看得舒服,我用最简单的一个demo来展示r ...

  9. 6周学习计划,攻克JavaScript难关(React/Redux/ES6 etc.)

    作者:余博伦链接:https://zhuanlan.zhihu.com/p/23412169来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 和大家一样,最近我也看了Jo ...

随机推荐

  1. .NET跨平台实践:用C#开发Linux守护进程(转)

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  2. 我的ORM之五-- 事务

    我的ORM索引 单库事务与分布式事务 单库事务: 性能更好,应用于一个数据库时的场景,当数据库发生变化,如拆分为多个服务器,代码需要修改. 分布式事务:性能相对较差,但有更大的适用场景.当数据库发生变 ...

  3. 设计模式之美:Strategy(策略)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):使用不同的 Strategy 处理内部状态. 别名 Policy 意图 定义一系列的算法,把它们一个个封装起来,并且使它们可以相 ...

  4. dojo的发展历史

    dojo的开始要从2004年初开始说起,那时dojo之父 Alex Russell 在Informatica公司内从事一个名为netWindows的项目,这个项目的目的是在浏览器环境下提供创建窗口化界 ...

  5. Programming Erlang 学习笔记(一)

    入门 启动Shell 在cmd中输入命令”erl”,百分号(%)表示一个注释的开始,从百分号开始到这行结束的所有文本都被看做是注释. 一个完整的命令需要以一个句点和一个回车结束. 退出erlang的命 ...

  6. OpenSSL密码算法库: MD5示例小程序

    OpenSSL http://www.openssl.org/ OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库.SSL协议库以及应用程序.OpenSSL 的密码算法库包含多种加密算 ...

  7. 测试博文中添加可执行JS代码

    昨天申请开通了博客园的JS权限,今天来看看效果. 测试执行JS 测试执行JS // 运行

  8. MYSQL 大文件无法导入的问题。

    1. 设置maxpacket. 要在[mysqld]标签下.这个疏忽了,就会发现没效果. 基本网上的都没说清,要看stackoverflow. Change in the my.ini file. I ...

  9. 【重要更新】Senparc.Weixin.Open v1.5.1

    本次更新调整了命名空间和文件位置,具体变化为(可以直接在源代码中替换): 旧命名空间(对应文件夹) 新命名空间(对应文件夹) Senparc.Weixin.Open.OAuth Senparc.Wei ...

  10. Nginx下WordPress的Rewrite

    最近接触WP Super Cache,该插件要求固定链接必须是重写的,故用到Rewrite. 我的是这样配置的: /usr/local/nginx/conf/rewrite/wordpress.con ...