在现代 Web 开发中,单页应用程序(Single Page Application,SPA)已经成为了主流。SPA 可以提供更加流畅的用户体验,同时也可以更好地支持移动设备。React 和 Redux 是目前最流行的前端开发框架之一,本文将介绍如何使用 React 和 Redux 开发一个简单的单页应用程序。
准备工作
在开始编写应用程序之前,需要安装 Node.js 和 npm。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,而 npm 是 Node.js 的包管理器。可以从 Node.js 官网(https://nodejs.org/)下载安装包,安装完成后可以通过命令行验证是否成功安装:
node -v npm -v
安装完成后,可以使用 npm 安装 React 和 Redux:
npm install react redux
创建应用程序
在开始编写应用程序之前,需要确定应用程序的结构。在本文中,我们将创建一个简单的待办事项应用程序。应用程序包含两个页面:待办事项列表和添加待办事项。我们将使用 React Router 来管理路由。
首先,创建一个名为 todo-app
的目录,并进入该目录:
mkdir todo-app cd todo-app
然后,使用 npm 初始化项目:
npm init
按照提示输入项目信息,完成后会生成一个 package.json
文件。
接下来,安装必要的依赖:
npm install react react-dom react-router-dom redux react-redux
创建项目的目录结构如下:
// javascriptcn.com 代码示例 todo-app/ |- node_modules/ |- src/ | |- components/ | | |- AddTodo.js | | |- Todo.js | | |- TodoList.js | |- pages/ | | |- AddTodoPage.js | | |- TodoListPage.js | |- reducers/ | | |- index.js | |- App.js | |- index.js |- package.json
其中,src
目录包含了应用程序的源代码,components
目录包含了可复用的组件,pages
目录包含了页面组件,reducers
目录包含了 Redux 的 reducer。
编写组件
我们先从编写组件开始。在 src/components
目录下,创建三个组件文件:Todo.js
、TodoList.js
和 AddTodo.js
。这些组件分别用于显示单个待办事项、待办事项列表和添加待办事项。
Todo.js
组件:
// javascriptcn.com 代码示例 import React from 'react'; const Todo = ({ todo }) => ( <div> <h2>{todo.title}</h2> <p>{todo.description}</p> </div> ); export default Todo;
TodoList.js
组件:
// javascriptcn.com 代码示例 import React from 'react'; import Todo from './Todo'; const TodoList = ({ todos }) => ( <div> {todos.map(todo => ( <Todo key={todo.id} todo={todo} /> ))} </div> ); export default TodoList;
AddTodo.js
组件:
// javascriptcn.com 代码示例 import React, { useState } from 'react'; const AddTodo = ({ onSubmit }) => { const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const handleSubmit = e => { e.preventDefault(); onSubmit({ title, description }); setTitle(''); setDescription(''); }; return ( <form onSubmit={handleSubmit}> <label> Title: <input type="text" value={title} onChange={e => setTitle(e.target.value)} /> </label> <label> Description: <textarea value={description} onChange={e => setDescription(e.target.value)} /> </label> <button type="submit">Add Todo</button> </form> ); }; export default AddTodo;
编写页面组件
在 src/pages
目录下,创建两个页面组件文件:TodoListPage.js
和 AddTodoPage.js
。这些页面组件用于渲染页面,包含了相应的路由信息。
TodoListPage.js
页面组件:
// javascriptcn.com 代码示例 import React from 'react'; import { connect } from 'react-redux'; import TodoList from '../components/TodoList'; import { fetchTodos } from '../reducers'; class TodoListPage extends React.Component { componentDidMount() { this.props.fetchTodos(); } render() { const { todos } = this.props; return ( <div> <h1>Todo List</h1> <TodoList todos={todos} /> </div> ); } } const mapStateToProps = state => ({ todos: state.todos, }); export default connect(mapStateToProps, { fetchTodos })(TodoListPage);
AddTodoPage.js
页面组件:
// javascriptcn.com 代码示例 import React from 'react'; import { connect } from 'react-redux'; import AddTodo from '../components/AddTodo'; import { addTodo } from '../reducers'; const AddTodoPage = ({ addTodo, history }) => { const handleSubmit = todo => { addTodo(todo); history.push('/'); }; return ( <div> <h1>Add Todo</h1> <AddTodo onSubmit={handleSubmit} /> </div> ); }; export default connect(null, { addTodo })(AddTodoPage);
编写 Redux reducer
在 src/reducers
目录下,创建 index.js
文件,编写 Redux 的 reducer。
// javascriptcn.com 代码示例 import { combineReducers } from 'redux'; const FETCH_TODOS = 'FETCH_TODOS'; const ADD_TODO = 'ADD_TODO'; export const fetchTodos = () => ({ type: FETCH_TODOS, }); export const addTodo = todo => ({ type: ADD_TODO, payload: todo, }); const todosReducer = (state = [], action) => { switch (action.type) { case FETCH_TODOS: return [ { id: 1, title: 'Todo 1', description: 'Description 1' }, { id: 2, title: 'Todo 2', description: 'Description 2' }, { id: 3, title: 'Todo 3', description: 'Description 3' }, ]; case ADD_TODO: return [...state, { ...action.payload, id: state.length + 1 }]; default: return state; } }; export default combineReducers({ todos: todosReducer, });
编写应用程序
在 src
目录下,创建 App.js
文件,编写应用程序的根组件。
// javascriptcn.com 代码示例 import React from 'react'; import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; import TodoListPage from './pages/TodoListPage'; import AddTodoPage from './pages/AddTodoPage'; const App = () => ( <Router> <div> <nav> <ul> <li> <Link to="/">Todo List</Link> </li> <li> <Link to="/add">Add Todo</Link> </li> </ul> </nav> <Route exact path="/" component={TodoListPage} /> <Route path="/add" component={AddTodoPage} /> </div> </Router> ); export default App;
在 src
目录下,创建 index.js
文件,渲染根组件。
// javascriptcn.com 代码示例 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import reducers from './reducers'; import App from './App'; const store = createStore(reducers); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
最后,在 index.html
文件中添加一个 div
:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo App</title> </head> <body> <div id="root"></div> <script src="dist/bundle.js"></script> </body> </html>
运行应用程序
在命令行中执行以下命令,编译应用程序:
npm run build
然后,在浏览器中打开 index.html
文件,即可看到应用程序界面。在待办事项列表页面中,将显示三个默认的待办事项。在添加待办事项页面中,可以添加新的待办事项。添加完成后,将自动跳转到待办事项列表页面,新添加的待办事项将显示在列表中。
总结
本文介绍了如何使用 React 和 Redux 开发一个简单的单页应用程序。通过本文的学习,可以了解 React 和 Redux 的基本用法,以及如何创建组件、页面和 reducer。同时,本文还介绍了如何使用 React Router 管理路由,以及如何使用 npm 管理依赖。
完整代码可在以下链接中找到:https://github.com/LucyBot-Inc/react-redux-todo-app。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6562a150d2f5e1655dc74912