前言
React 和 Redux 是目前前端开发中非常流行的技术栈,本文将使用 React 和 Redux 来实现一个 TodoList 的功能。本文主要介绍 TodoList 的基本功能实现,包括数据的增删改查等,旨在帮助初学者更好地理解 React 和 Redux 的使用方法。
技术栈
- React
- Redux
功能实现
1. 初始化项目
首先,我们需要使用 create-react-app
初始化一个 React 项目,具体步骤如下:
npx create-react-app todo-list cd todo-list npm start
2. 安装依赖
在项目根目录下,运行以下命令安装依赖:
npm install redux react-redux --save
3. 创建 Redux store
在 src
目录下创建一个名为 store.js
的文件,用于创建 Redux store。
import { createStore } from 'redux'; import rootReducer from './reducers'; const store = createStore(rootReducer); export default store;
我们在 store.js
中使用 createStore
方法创建了一个 Redux store,并将根 reducer 传递给了 createStore
方法。rootReducer
是一个由多个 reducer 组成的对象,我们将在后面的步骤中创建。
4. 创建 reducer
在 src
目录下创建一个名为 reducers.js
的文件,用于创建 reducer。
// javascriptcn.com 代码示例 import { ADD_TODO, DELETE_TODO, EDIT_TODO, COMPLETE_TODO, COMPLETE_ALL, CLEAR_COMPLETED } from './actionTypes'; const initialState = { todos: [] }; function rootReducer(state = initialState, action) { switch (action.type) { case ADD_TODO: return { ...state, todos: [ ...state.todos, { id: action.id, text: action.text, completed: false } ] }; case DELETE_TODO: return { ...state, todos: state.todos.filter(todo => todo.id !== action.id) }; case EDIT_TODO: return { ...state, todos: state.todos.map(todo => { if (todo.id === action.id) { return { ...todo, text: action.text }; } return todo; }) }; case COMPLETE_TODO: return { ...state, todos: state.todos.map(todo => { if (todo.id === action.id) { return { ...todo, completed: !todo.completed }; } return todo; }) }; case COMPLETE_ALL: const areAllMarked = state.todos.every(todo => todo.completed); return { ...state, todos: state.todos.map(todo => ({ ...todo, completed: !areAllMarked })) }; case CLEAR_COMPLETED: return { ...state, todos: state.todos.filter(todo => !todo.completed) }; default: return state; } } export default rootReducer;
在 reducers.js
中,我们定义了一个名为 rootReducer
的 reducer 函数,它接收两个参数:state
和 action
。state
是当前的状态,action
是一个描述状态变化的对象。
在 rootReducer
中,我们使用 switch
语句来处理不同的 action 类型,根据 action 类型的不同,对 state 进行不同的操作。例如,当 action 类型为 ADD_TODO
时,我们会将新的 todo 添加到 todos 数组中。
5. 创建 action
在 src
目录下创建一个名为 actions.js
的文件,用于创建 action。
// javascriptcn.com 代码示例 import { ADD_TODO, DELETE_TODO, EDIT_TODO, COMPLETE_TODO, COMPLETE_ALL, CLEAR_COMPLETED } from './actionTypes'; let nextTodoId = 0; export const addTodo = text => ({ type: ADD_TODO, id: nextTodoId++, text }); export const deleteTodo = id => ({ type: DELETE_TODO, id }); export const editTodo = (id, text) => ({ type: EDIT_TODO, id, text }); export const completeTodo = id => ({ type: COMPLETE_TODO, id }); export const completeAll = () => ({ type: COMPLETE_ALL }); export const clearCompleted = () => ({ type: CLEAR_COMPLETED });
在 actions.js
中,我们定义了多个 action,例如 addTodo
、deleteTodo
、editTodo
等。每个 action 都是一个函数,它返回一个 action 对象,这个对象描述了该 action 的类型和需要传递的数据。
6. 创建 TodoList 组件
在 src
目录下创建一个名为 TodoList.js
的文件,用于创建 TodoList 组件。
// javascriptcn.com 代码示例 import React, { Component } from 'react'; import { connect } from 'react-redux'; import { addTodo, deleteTodo, editTodo, completeTodo, completeAll, clearCompleted } from './actions'; class TodoList extends Component { constructor(props) { super(props); this.state = { inputValue: '' }; } handleInputChange = e => { this.setState({ inputValue: e.target.value }); }; handleInputKeyDown = e => { const inputValue = e.target.value.trim(); if (e.keyCode === 13 && inputValue) { this.props.addTodo(inputValue); this.setState({ inputValue: '' }); } }; handleToggleAllChange = e => { this.props.completeAll(); }; handleClearCompletedClick = () => { this.props.clearCompleted(); }; render() { const { todos, deleteTodo, editTodo, completeTodo } = this.props; const { inputValue } = this.state; return ( <div> <header> <h1>TodoList</h1> <input type="text" placeholder="What needs to be done?" autoFocus={true} value={inputValue} onChange={this.handleInputChange} onKeyDown={this.handleInputKeyDown} /> </header> <section> <input type="checkbox" checked={todos.every(todo => todo.completed)} onChange={this.handleToggleAllChange} /> <ul> {todos.map(todo => ( <li key={todo.id}> <div> <input type="checkbox" checked={todo.completed} onChange={() => completeTodo(todo.id)} /> <input type="text" value={todo.text} onChange={e => editTodo(todo.id, e.target.value)} /> <button onClick={() => deleteTodo(todo.id)}>X</button> </div> </li> ))} </ul> </section> <footer> <span>{todos.filter(todo => !todo.completed).length} items left</span> <button onClick={this.handleClearCompletedClick}>Clear completed</button> </footer> </div> ); } } const mapStateToProps = state => ({ todos: state.todos }); const mapDispatchToProps = { addTodo, deleteTodo, editTodo, completeTodo, completeAll, clearCompleted }; export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
在 TodoList.js
中,我们定义了一个名为 TodoList
的组件,它包含了一个 header、一个 section 和一个 footer,用于显示 TodoList 的内容。
在 TodoList
的构造函数中,我们初始化了一个名为 inputValue
的状态,用于存储用户输入的内容。
在 TodoList
中,我们使用了 Redux 中的 connect
方法将 TodoList
组件和 store
进行了连接。mapStateToProps
函数用于将 store
中的状态映射到 TodoList
的 props 中,mapDispatchToProps
对象用于将 action 映射到 TodoList
的 props 中。
在 TodoList
中,我们使用了多个事件处理函数,例如 handleInputChange
、handleInputKeyDown
、handleToggleAllChange
等。这些事件处理函数用于处理用户的交互,例如添加 todo、删除 todo、编辑 todo 等。
7. 渲染 TodoList 组件
在 src/index.js
文件中,我们将 TodoList
组件渲染到页面中。
// javascriptcn.com 代码示例 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import store from './store'; import TodoList from './TodoList'; ReactDOM.render( <Provider store={store}> <TodoList /> </Provider>, document.getElementById('root') );
在 index.js
中,我们使用了 React 中的 ReactDOM.render
方法将 TodoList
组件渲染到页面中。我们还使用了 Redux 中的 Provider
组件将 store
传递给了 TodoList
组件。
总结
本文主要介绍了使用 React 和 Redux 实现一个 TodoList 的功能。我们使用了 create-react-app
初始化了一个 React 项目,使用了 Redux 来管理 TodoList 的状态。通过本文的学习,我们可以更好地理解 React 和 Redux 的使用方法,并掌握如何使用它们来实现一个功能完整的应用程序。
示例代码
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/657fe6d1d2f5e1655dad4430