用redux完成事务清单

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

App.js

 1 import React, { PropTypes } from ‘react‘
 2 import { bindActionCreators } from ‘redux‘
 3 import { connect } from ‘react-redux‘
 4 import Header from ‘../components/Header‘
 5 import MainSection from ‘../components/MainSection‘
 6 import * as TodoActions from ‘../actions‘
 7
 8 const App = ({todos, actions}) => (
 9   <div>
10     <Header addTodo={actions.addTodo} /> //头部负责添加事项
11     <MainSection todos={todos} actions={actions} />  //这是2个组件
12   </div>
13 )
14
15 App.propTypes = {
16   todos: PropTypes.array.isRequired,
17   actions: PropTypes.object.isRequired  //todos是数组  actions是对象
18 }
19
20 const mapStateToProps = state => ({
21   todos: state.todos
22 })
23
24 const mapDispatchToProps = dispatch => ({
25     actions: bindActionCreators(TodoActions, dispatch)
26 })
27
28 export default connect(
29   mapStateToProps,
30   mapDispatchToProps
31 )(App)

head.js

 1 import React, { PropTypes, Component } from ‘react‘
 2 import TodoTextInput from ‘./TodoTextInput‘
 3
 4 export default class Header extends Component {  //es6组建写法
 5   static propTypes = {
 6     addTodo: PropTypes.func.isRequired
 7   }
 8
 9   handleSave = text => {
10     if (text.length !== 0) {
11       this.props.addTodo(text)
12     }
13   }
14
15   render() {
16     return (
17       <header className="header">
18         <h1>todos</h1>
19         <TodoTextInput newTodo
20                        onSave={this.handleSave} //添加事项
21                        placeholder="What needs to be done?" />
22       </header>
23     )
24   }
25 }
TodoTextInput.js
 1 import React, { Component, PropTypes } from ‘react‘
 2 import classnames from ‘classnames‘
 3
 4 export default class TodoTextInput extends Component {
 5   static propTypes = {
 6     onSave: PropTypes.func.isRequired,
 7     text: PropTypes.string,
 8     placeholder: PropTypes.string,
 9     editing: PropTypes.bool,
10     newTodo: PropTypes.bool
11   }
12
13   state = {
14     text: this.props.text || ‘‘
15   }
16
17   handleSubmit = e => {
18     const text = e.target.value.trim()
19     if (e.which === 13) {
20       this.props.onSave(text)  //保存文本值
21       if (this.props.newTodo) {
22         this.setState({ text: ‘‘ })
23       }
24     }
25   }
26
27   handleChange = e => {
28     this.setState({ text: e.target.value })
29   }
30
31   handleBlur = e => {
32     if (!this.props.newTodo) {
33       this.props.onSave(e.target.value)
34     }
35   }
36
37   render() {
38     return (
39       <input className={
40         classnames({
41           edit: this.props.editing,
42           ‘new-todo‘: this.props.newTodo
43         })}
44         type="text"
45         placeholder={this.props.placeholder} //what needs to be done?
46         autoFocus="true"
47         value={this.state.text}
48         onBlur={this.handleBlur}
49         onChange={this.handleChange}  //改变state里面的值
50         onKeyDown={this.handleSubmit} /> //keycode=13 提交保存
51     )
52   }
53 }

mainSection.js

 1 import React, { Component, PropTypes } from ‘react‘
 2 import TodoItem from ‘./TodoItem‘
 3 import Footer from ‘./Footer‘
 4 import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from ‘../constants/TodoFilters‘ //过滤器
 5
 6 const TODO_FILTERS = {
 7   [SHOW_ALL]: () => true,
 8   [SHOW_ACTIVE]: todo => !todo.completed,
 9   [SHOW_COMPLETED]: todo => todo.completed
10 }
11
12 export default class MainSection extends Component {
13   static propTypes = {
14     todos: PropTypes.array.isRequired,
15     actions: PropTypes.object.isRequired
16   }
17
18   state = { filter: SHOW_ALL }
19
20   handleClearCompleted = () => {
21     this.props.actions.clearCompleted() //清除完成事项
22   }
23
24   handleShow = filter => {
25     this.setState({ filter })  //根据过滤条件展示
26   }
27
28   renderToggleAll(completedCount) {
29     const { todos, actions } = this.props
30     if (todos.length > 0) {
31       return (
32         <input className="toggle-all"
33                type="checkbox"
34                checked={completedCount === todos.length} //是否全部完成
35                onChange={actions.completeAll} />
36       )
37     }
38   }
39
40   renderFooter(completedCount) {
41     const { todos } = this.props
42     const { filter } = this.state
43     const activeCount = todos.length - completedCount
44
45     if (todos.length) {
46       return (
47         <Footer completedCount={completedCount}
48                 activeCount={activeCount}
49                 filter={filter}
50                 onClearCompleted={this.handleClearCompleted.bind(this)}
51                 onShow={this.handleShow.bind(this)} />
52       )
53     }
54   }
55
56   render() {
57     const { todos, actions } = this.props
58     const { filter } = this.state
59
60     const filteredTodos = todos.filter(TODO_FILTERS[filter])  //初始值为showall 展示全部
61     const completedCount = todos.reduce((count, todo) =>   //统计已完成事项
62       todo.completed ? count + 1 : count,
63       0
64     )
65
66     return (
67       <section className="main">
68         {this.renderToggleAll(completedCount)}
69         <ul className="todo-list">
70           {filteredTodos.map(todo =>
71             <TodoItem key={todo.id} todo={todo} {...actions} />
72           )}
73         </ul>
74         {this.renderFooter(completedCount)}
75       </section>
76     )
77   }
78 }

todoItems.js

 1 import React, { Component, PropTypes } from ‘react‘
 2 import classnames from ‘classnames‘
 3 import TodoTextInput from ‘./TodoTextInput‘
 4
 5 export default class TodoItem extends Component {
 6   static propTypes = {
 7     todo: PropTypes.object.isRequired,
 8     editTodo: PropTypes.func.isRequired,
 9     deleteTodo: PropTypes.func.isRequired,
10     completeTodo: PropTypes.func.isRequired
11   }
12
13   state = {
14     editing: false
15   }
16
17   handleDoubleClick = () => {
18     this.setState({ editing: true })
19   }
20
21   handleSave = (id, text) => {
22     if (text.length === 0) {
23       this.props.deleteTodo(id)
24     } else {
25       this.props.editTodo(id, text)   //编辑  不存在text则删除该项
26     }
27     this.setState({ editing: false })
28   }
29
30   render() {
31     const { todo, completeTodo, deleteTodo } = this.props
32
33     let element
34     if (this.state.editing) {
35       element = (
36         <TodoTextInput text={todo.text}
37                        editing={this.state.editing}
38                        onSave={(text) => this.handleSave(todo.id, text)} />
39       )
40     } else {
41       element = (
42         <div className="view">
43           <input className="toggle"
44                  type="checkbox"
45                  checked={todo.completed}
46                  onChange={() => completeTodo(todo.id)} />
47           <label onDoubleClick={this.handleDoubleClick}>  //双击修改为可编辑状态   会重新渲染
48             {todo.text}
49           </label>
50           <button className="destroy"
51                   onClick={() => deleteTodo(todo.id)} />
52         </div>
53       )
54     }
55
56     return (
57       <li className={classnames({
58         completed: todo.completed,
59         editing: this.state.editing
60       })}>
61         {element}
62       </li>
63     )
64   }
65 }

footer.js

 1 import React, { PropTypes, Component } from ‘react‘
 2 import classnames from ‘classnames‘
 3 import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from ‘../constants/TodoFilters‘
 4
 5 const FILTER_TITLES = {
 6   [SHOW_ALL]: ‘All‘,
 7   [SHOW_ACTIVE]: ‘Active‘,
 8   [SHOW_COMPLETED]: ‘Completed‘
 9 }
10
11 export default class Footer extends Component {
12   static propTypes = {
13     completedCount: PropTypes.number.isRequired,
14     activeCount: PropTypes.number.isRequired,
15     filter: PropTypes.string.isRequired,
16     onClearCompleted: PropTypes.func.isRequired,
17     onShow: PropTypes.func.isRequired
18   }
19
20   renderTodoCount() {
21     const { activeCount } = this.props
22     const itemWord = activeCount === 1 ? ‘item‘ : ‘items‘  //此处语法经典
23
24     return (
25       <span className="todo-count">
26         <strong>{activeCount || ‘No‘}</strong> {itemWord} left  //有多少未完成事项
27       </span>
28     )
29   }
30
31   renderFilterLink(filter) {
32     const title = FILTER_TITLES[filter]
33     const { filter: selectedFilter, onShow } = this.props
34
35     return (
36       <a className={classnames({ selected: filter === selectedFilter })}
37          style={{ cursor: ‘pointer‘ }}
38          onClick={() => onShow(filter)}>
39         {title}
40       </a>
41     )
42   }
43
44   renderClearButton() {
45     const { completedCount, onClearCompleted } = this.props
46     if (completedCount > 0) {
47       return (
48         <button className="clear-completed"
49                 onClick={onClearCompleted} >
50           Clear completed
51         </button>
52       )
53     }
54   }
55
56   render() {
57     return (
58       <footer className="footer">
59         {this.renderTodoCount()}
60         <ul className="filters">
61           {[ SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED ].map(filter =>
62             <li key={filter}>
63               {this.renderFilterLink(filter)}   //切换不同的过滤条件
64             </li>
65           )}
66         </ul>
67         {this.renderClearButton()}
68       </footer>
69     )
70   }
71 }

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

indes.js

1 import * as types from ‘../constants/ActionTypes‘
2
3 export const addTodo = text => ({ type: types.ADD_TODO, text })
4 export const deleteTodo = id => ({ type: types.DELETE_TODO, id })
5 export const editTodo = (id, text) => ({ type: types.EDIT_TODO, id, text })  //这一看就是dispatch的内容
6 export const completeTodo = id => ({ type: types.COMPLETE_TODO, id })
7 export const completeAll = () => ({ type: types.COMPLETE_ALL })
8 export const clearCompleted = () => ({ type: types.CLEAR_COMPLETED })

todo.js

 1 import { ADD_TODO, DELETE_TODO, EDIT_TODO, COMPLETE_TODO, COMPLETE_ALL, CLEAR_COMPLETED } from ‘../constants/ActionTypes‘
 2
 3 const initialState = [
 4   {
 5     text: ‘Use Redux‘,
 6     completed: false,
 7     id: 0               //初始化state
 8   }
 9 ]
10
11 export default function todos(state = initialState, action) {
12   switch (action.type) {
13     case ADD_TODO:
14       return [
15         {
16           id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1, //确定id值
17           completed: false,
18           text: action.text
19         },
20         ...state
21       ]
22
23     case DELETE_TODO:
24       return state.filter(todo =>
25         todo.id !== action.id
26       )
27
28     case EDIT_TODO:
29       return state.map(todo =>
30         todo.id === action.id?
31         (...todo,{text:action.text}):
32          todo
33       )
34
35     case COMPLETE_TODO:
36       return state.map(todo =>
37         todo.id === action.id ?
38           { ...todo, completed: !todo.completed } : //用于切换
39           todo
40       )
41
42     case COMPLETE_ALL:
43       const areAllMarked = state.every(todo => todo.completed) //全部完成 或全部未完成
44       return state.map(todo => ({
45         ...todo,
46         completed: !areAllMarked
47       }))
48
49     case CLEAR_COMPLETED:
50       return state.filter(todo => todo.completed === false)
51
52     default:
53       return state
54   }
55 }

index.js  整合reducers

1 import { combineReducers } from ‘redux‘
2 import todos from ‘./todos‘
3
4 const rootReducer = combineReducers({
5   todos
6 })
7
8 export default rootReducer

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

 
时间: 2025-01-19 21:52:40

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

事务与数据库恢复原理

事务与数据库恢复原理 数据存储的逻辑单位是数据块,数据操作的逻辑单位是事务. 事务是用户定义的一组操作序列,有一条或多条相关SQL语句组成,是数据库应用程序的基本逻辑单位.事务管理技术主要包括数据库的恢复技术和并发控制技术. 事务的处理逻辑过程 1. 服务器进程捡取该事务的SQL语句,然后检查共享池,查看是否包含该SQL语句的共享SQL区. 2. 如有,则检查该用户是否有访问所涉及的数据的权限,如有,则使用共享SQL区处理该SQL语句.如果没有找到共享SQL区,则分配一个新的SQL区,以便分析.

数据库的基本常识

数据库第四版答案(王珊 萨师煊)           1 .试述数据.数据库.数据库系统.数据库管理系统的概念. 答: ( l )数据( Data ) :描述事物的符号记录称为数据.数据的种类有数字.文字.图形.图像.声音.正文等.数据与其语义是不可分的.解析在现代计算机系统中数据的概念是广义的.早期的计算机系统主要用于科学计算,处理的数据是整数.实数.浮点数等传统数学中的数据.现代计算机能存储和处理的对象十分广泛,表示这些对象的数据也越来越复杂.数据与其语义是不可分的. 500 这个数字可以表

读书笔记:《搞定3--平衡工作和生活的艺术》

读书笔记:<搞定3--平衡工作和生活的艺术> 这本<搞定3>是在来回上海的飞机上看了一半,回来后慢慢看完的.感觉这本书把<搞定1>的思路理得更加清晰了,用一张图可以表示出文章的大纲结构. 前三章 讲述了GTD现象.为什么有用.GTD的原则.3种模型.思想基础.步骤.自我管理矩阵. GTD有用的主要原因是:当一件事总放在脑子里,在做任何事的时候总想着它,从而造成了干扰.分心与压力,当你把它写了下来后,从而压力大大减轻. 三种GTD模型:掌控工作流程.合乎自然的规划.关注层

Spring Transaction 使用入门

一.开篇陈述 1.1 写文缘由 最近在系统学习spring框架IoC.AOP.Transaction相关的知识点,准备写三篇随笔记录学习过程中的感悟.这是第一篇,记录spring Transaction的使用及部分原理.spring的学习过程应该是从IoC到AOP再到Transaction,这里写随笔的顺序没有按照学习路线. 1.2 预备技能 学习spring事务使用最好具备基础的Java知识,掌握spring IoC和spring AOP,并对各类数据库事务的概念有所了解.当然,这些都不是必须

数据库 - 恢复策略与数据库镜像

登记日志文件 基本原则 登记的次序严格按并行事务执行的时间次序 必须先写日志文件,后写数据库 写日志文件操作:把表示这个修改的日志记录 写到日志文件 写数据库操作:把对数据的修改写到数据库中 为什么要先写日志文件 (The Write-Ahead Log) 写数据库和写日志文件是两个不同的操作 在这两个操作之间可能发生故障 如果先写了数据库修改,而在日志文件中没有登记下这个修改,则以后就无法恢复这个修改了 如果先写日志,但没有修改数据库,按日志文件恢复时只不过是多执行一次不必要的UNDO操作,并

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

MainActivity public class MainActivity extends ListActivity {     private TextView tv_info;     private EditText editText;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         List

不经意间回了个头

从哪里说起呢?从当下说起吧. 炙热的太阳出现在天空的时候,我以为夏天来了.在接下来的几天里,急转直下的温度,连日绵绵的春雨,让我认识到我太天真了.雨停了之后的两天是伴随着大风的晴天,阳光虽然耀眼,但仍两股瑟瑟.今天上午的一声闷雷,我抬头一看,哦,又要下雨了…… 西安可没有这么多的雨.于是,我开始回忆在西安的日子……呵呵,是的.我离开西安了,走的很匆忙,在走之前脑子里过了很多遍的事务清单都没有做,想着,离开之前,要知会老友,拜会恩师,再攀一次秦岭看看母校,登一次城墙凝望长安……遗憾总是有的,人生岂

数据库系统概论(第四版)习题解答

数据库系统概论(第四版) 第1章 绪论 1 .试述数据.数据库.数据库系统.数据库管理系统的概念. 答:( l )数据( Data ) :描述事物的符号记录称为数据.数据的种类有数字.文字.图形.图像.声音.正文等.数据与其语义是不可分的.解析在现代计算机系统中数据的概念是广义的.早期的计算机系统主要用于科学计算,处理的数据是整数.实数.浮点数等传统数学中的数据.现代计算机能存储和处理的对象十分广泛,表示这些对象的数据也越来越复杂.数据与其语义是不可分的. 500 这个数字可以表示一件物品的价格

如何学习(Java)

这篇文章旨在初学者如何学习Java.随着我们成长,我们有规律的学习新的内容.怎样走路,怎样吃饭,怎样绘画,怎样计算数学,怎样接吻等等.这些事情共同点是什么呢?这些学习最大的共同点是如何学习? 我认识的一个软件设计师,曾经在从美国到印度的飞机上阅读一本RESTful服务书.在那趟飞机旅途中,他从头至尾阅读了那本书,并且还看了一部电影.然后,他把书给他们团队,接着设计了一个RESTful API平台,并用平台的开发指导我们. 这些全是关于如何学习和 因兴趣开始, 有动力推动, 寻找合适的资源, 吸收