项目实战:构建一个Web应用(上篇)

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 项目实战:构建一个Web应用(上篇)

## 1. 项目简介

### 1.1 技术栈

以下是本项目实战所使用的技术栈:

- 后端:Node.js、Express

- 数据库:MongoDB

- 前端(下篇文章中):HTML、CSS、JavaScript、Bootstrap、jQuery

- 版本控制:Git

## 2. 项目准备

### 2.1 安装相关工具

确保你已经安装了以下工具:

1. [Node.js](https://nodejs.org/)

2. [npm](https://www.npmjs.com/)(Node.js包管理工具,通常与Node.js一起安装)

3. [Git](https://git-scm.com/)

4. [MongoDB](https://www.mongodb.com/)

### 2.2 创建项目文件夹

打开命令行工具,创建项目文件夹并进入:

1. mkdir todo-app
2. cd todo-app

### 2.3 初始化Git仓库

在项目文件夹中初始化Git仓库:

git init

创建`.gitignore`文件,排除一些不需要跟踪的文件和文件夹:

node_modules/
*.log

## 3. 后端搭建

### 3.1 初始化项目

运行`npm init`,按照提示填写信息,初始化项目。这将生成一个`package.json`文件,用于管理项目依赖和配置。

### 3.2 安装依赖

安装后端所需的依赖:

npm install express mongoose bcryptjs jsonwebtoken

- express:Web应用框架

- mongoose:MongoDB对象模型工具

- bcryptjs:加密库

- jsonwebtoken:生成和验证JSON Web Token(JWT

### 3.3 搭建服务器

创建一个名为`server.js`的文件,并写入以下代码:

const express = require("express");
const app = express();
// 使用JSON中间件来解析请求体
app.use(express.json());
app.get("/", (req, res) => {
  res.send("Hello World!");
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

运行`node server.js`启动服务器,访问`http://localhost:3000`,你应该看到"Hello World!"。

### 3.4 数据库连接

确保你已经安装并启动了MongoDB。在`server.js`中添加以下代码以连接数据库:

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/todo_app", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
  .then(() => console.log("Connected to MongoDB"))
  .catch((err) => console.error("Could not connect to MongoDB", err));

现在,我们已经成功连接到了MongoDB数据库。接下来,我们将创建用户认证和待办事项相关的接口。

### 3.5 用户认证

首先,我们要创建用户模型。在项目根目录下创建一个名为`models`的文件夹。然后,在`models`文件夹中创建一个名为`user.js`的文件,并添加以下代码:

const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true,
  },
  password: {
    type: String,
    required: true,
  },
});
// 在保存用户之前,对密码进行哈希处理
userSchema.pre("save", async function (next) {
  if (!this.isModified("password")) return next();
  this.password = await bcrypt.hash(this.password, 10);
  next();
});
// 验证密码的实例方法
userSchema.methods.validatePassword = function (password) {
  return bcrypt.compare(password, this.password);
};
const User = mongoose.model("User", userSchema);
module.exports = User;

接下来,我们将创建注册和登录接口。在项目根目录下创建一个名为`routes`的文件夹。然后,在`routes`文件夹中创建一个名为`auth.js`的文件,并添加以下代码:

const express = require("express");
const router = express.Router();
const jwt = require("jsonwebtoken");
const User = require("../models/user");
router.post("/register", async (req, res) => {
  try {
    const user = new User(req.body);
    await user.save();
    res.status(201).send({ message: "User registered successfully" });
  } catch (err) {
    res.status(400).send({ error: err.message });
  }
});
router.post("/login", async (req, res) => {
  try {
    const user = await User.findOne({ username: req.body.username });
    if (!user || !(await user.validatePassword(req.body.password))) {
      throw new Error("Invalid username or password");
    }
    const token = jwt.sign({ userId: user._id }, "your_jwt_secret");
    res.send({ token });
  } catch (err) {
    res.status(401).send({ error: err.message });
  }
});
module.exports = router;

最后,在`server.js`中添加以下代码来挂载认证路由:

const authRoutes = require("./routes/auth");
// ...
app.use("/auth", authRoutes);
// ...

现在,我们已经完成了用户认证相关的接口。可以使用Postman等API测试工具测试注册和登录接口。

### 3.6 待办事项接口

首先,我们要创建待办事项模型。在`models`文件夹中创建一个名为`todo.js`的文件,并添加以下代码:

const mongoose = require("mongoose");
const todoSchema = new mongoose.Schema({
  userId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
    required: true,
  },
  title: {
    type: String,
    required: true,
  },
  completed: {
    type: Boolean,
    default: false,
  },
});
const Todo = mongoose.model("Todo", todoSchema);
module.exports = Todo;

接下来,我们将创建待办事项相关的接口。在`routes`文件夹中创建一个名为`todos.js`的文件,并添加以下代码:

const express = require("express");
const router = express.Router();
const Todo = require("../models/todo");
router.get("/", async (req, res) => {
  try {
    const todos = await Todo.find({});
    res.send(todos);
  } catch (err) {
    res.status(500).send({ error: err.message });
  }
});
router.post("/", async (req, res) => {
  try {
    const todo = new Todo(req.body);
    await todo.save();
    res.status(201).send(todo);
  } catch (err) {
    res.status(400).send({ error: err.message });
  }
});
router.put("/:id", async (req, res) => {
  try {
    const todo = await Todo.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
      runValidators: true,
    });
    if (!todo) throw new Error("Todo not found");
    res.send(todo);
  } catch (err) {
    res.status(400).send({ error: err.message });
  }
});
router.delete("/:id", async (req, res) => {
  try {
    const todo = await Todo.findByIdAndDelete(req.params.id);
    if (!todo) throw new Error("Todo not found");
    res.send({ message: "Todo deleted successfully" });
  } catch (err) {
    res.status(400).send({ error: err.message });
  }
});
module.exports = router;

最后,在`server.js`中添加以下代码来挂载待办事项路由:

1. const todoRoutes = require("./routes/todos");
2. 
3. // ...
4. 
5. app.use("/todos", todoRoutes);
6. 
7. // ...

至此,我们已经完成了待办事项接口的开发。可以使用Postman等API测试工具测试待办事项相关接口。

## 4. 启动Web应用

在完成上篇文章中的步骤后,我们已经搭建好了后端服务器。现在我们需要启动后端服务器:

1. 确保已经安装并运行了MongoDB。

2. 打开命令行(终端),进入项目文件夹`todo-app`。

1. cd todo-app
2. ```

3. 运行`server.js`文件以启动服务器:

node server.js
```
如果一切正常,你应该看到以下输出:
````sh
Server running on port 3000
Connected to MongoDB
```

现在,后端服务器已经在端口3000上运行,并与MongoDB数据库连接。接下来,我们将构建前端部分。

## 5. 前端搭建

### 5.1 创建前端文件夹和文件

在项目根目录下创建一个名为`public`的文件夹,用于存放前端文件。接下来,在`public`文件夹中创建以下文件:

- `index.html`:主页面

- `style.css`:样式表

- `script.js`:JavaScript脚本

### 5.2 编写前端页面

编辑`index.html`文件,添加以下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todo App</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1 class="text-center mt-5">Todo App</h1>
        <!-- 在这里添加表单和待办事项列表 -->
    </div>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <script src="script.js"></script>
</body>
</html>

5.3 添加表单和待办事项列表

index.html文件的<!-- 在这里添加表单和待办事项列表 -->位置添加以下代码:

<form class="mt-4" id="todo-form">
    <div class="form-group">
        <label for="title">Title</label>
        <input type="text" class="form-control" id="title" placeholder="Enter todo title">
    </div>
    <button type="submit" class="btn btn-primary">Add Todo</button>
</form>
<div class="mt-4">
    <h3 class="mb-3">Todo List</h3>
    <ul class="list-group" id="todo-list">
        <!-- 在这里显示待办事项 -->
    </ul>
</div>

5.4 编写CSS样式

编辑style.css文件,添加以下代码:

body {
    font-family: Arial, sans-serif;
}
.completed {
    text-decoration: line-through;
}

5.5 编写JavaScript脚本

编辑script.js文件,添加以下代码:

$(document).ready(function () {
  // 获取待办事项列表
  function getTodos() {
    // 在这里编写获取待办事项列表的代码
  }
  // 添加待办事项
  function addTodo() {
    // 在这里编写添加待办事项的代码
  }
  // 修改待办事项状态
  function toggleTodo() {
    // 在这里编写修改待办事项状态的代码
  }
  // 删除待办事项
  function deleteTodo() {
    // 在这里编写删除待办事项的代码
  }
  // 事件绑定
  $("#todo-form").on("submit", function (event) {
    event.preventDefault();
    addTodo();
  });
  $("#todo-list").on("click", ".toggle-todo", function () {
    toggleTodo();
  });
  $("#todo-list").on("click", ".delete-todo", function () {
    deleteTodo();
  });
  // 初始化
  getTodos();
});
``在`script.js`中,我们已经创建了基本的函数框架。接下来,我们需要实现这些函数,以便与后端服务器进行交互。
### 5.6 实现获取待办事项列表函数
在`getTodos`函数中添加以下代码:
```javascript
$.get("/api/todos", function (data) {
  $("#todo-list").empty();
  data.forEach(function (todo) {
    var listItem = $("<li class='list-group-item d-flex justify-content-between align-items-center'></li>");
    var title = $("<span class='todo-title'></span>").text(todo.title);
    if (todo.completed) {
      title.addClass("completed");
    }
    var buttonGroup = $("<div class='btn-group'></div>");
    var toggleButton = $("<button class='btn btn-sm btn-outline-secondary toggle-todo'></button>").text(todo.completed ? "Undo" : "Complete");
    var deleteButton = $("<button class='btn btn-sm btn-outline-danger delete-todo'></button>").text("Delete");
    buttonGroup.append(toggleButton, deleteButton);
    listItem.append(title, buttonGroup);
    listItem.data("id", todo._id);
    listItem.data("completed", todo.completed);
    $("#todo-list").append(listItem);
  });
});

5.7 实现添加待办事项函数

addTodo函数中添加以下代码:

var title = $("#title").val().trim();
if (title) {
  $.post("/api/todos", { title: title }, function () {
    $("#title").val("");
    getTodos();
  });
}

5.8 实现修改待办事项状态函数

toggleTodo函数中添加以下代码:

var listItem = $(this).closest("li");
var id = listItem.data("id");
var completed = listItem.data("completed");
$.ajax({
  url: "/api/todos/" + id,
  type: "PUT",
  data: { completed: !completed },
  success: function () {
    getTodos();
  }
});

5.9 实现删除待办事项函数

deleteTodo函数中添加以下代码:

var listItem = $(this).closest("li");
var id = listItem.data("id");
$.ajax({
  url: "/api/todos/" + id,
  type: "DELETE",
  success: function () {
    getTodos();
  }
});

至此,我们已经完成了前端页面的构建。现在,你可以运行后端服务器,然后在浏览器中访问http://localhost:3000来查看并使用这个待办事项应用。

为了使应用在 Express 服务器中正确运行,请确保在 server.js 文件中添加以下代码:

app.use(express.static("public"));

确保将其添加到其他中间件之前,例如:

const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const app = express();
const PORT = process.env.PORT || 3000;
mongoose.connect("mongodb://localhost/todo_app", { useNewUrlParser: true, useUnifiedTopology: true });
mongoose.set("useFindAndModify", false);
app.use(cors());
app.use(express.json());
app.use(express.static("public")); // 将此行添加到此处
app.use("/api/todos", require("./routes/todos"));
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

其他内容我们下篇再继续 可以订阅本专栏 有更新 第一时间推送给你。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
10天前
|
安全 Linux 开发工具
零基础构建开源项目OpenIM桌面应用和pc web- Electron篇
OpenIM 为开发者提供开源即时通讯 SDK,作为 Twilio、Sendbird 等云服务的替代方案。借助 OpenIM,开发者可以构建安全可靠的即时通讯应用,如 WeChat、Zoom、Slack 等。 本仓库基于开源版 OpenIM SDK 开发,提供了一款基于 Electron 的即时通讯应用。您可以使用此应用程序作为 OpenIM SDK 的参考实现。本项目同时引用了 @openim/electron-client-sdk 和 @openim/wasm-client-sdk,分别为 Electron 版本和 Web 版本的 SDK,可以同时构建 PC Web 程序和桌面应用(Wi
28 2
|
1月前
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
使用Web浏览器访问UE应用的最佳实践
|
2月前
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
|
2月前
|
弹性计算 负载均衡 安全
云端问道-Web应用上云经典架构方案教学
本文介绍了企业业务上云的经典架构设计,涵盖用户业务现状及挑战、阿里云业务托管架构设计、方案选型配置及业务初期低门槛使用等内容。通过详细分析现有架构的问题,提出了高可用、安全、可扩展的解决方案,并提供了按量付费的低成本选项,帮助企业在业务初期顺利上云。
|
2月前
|
弹性计算 Java 数据库
Web应用上云经典架构实战
本课程详细介绍了Web应用上云的经典架构实战,涵盖前期准备、配置ALB、创建服务器组和监听、验证ECS公网能力、环境配置(JDK、Maven、Node、Git)、下载并运行若依框架、操作第二台ECS以及验证高可用性。通过具体步骤和命令,帮助学员快速掌握云上部署的全流程。
|
2月前
|
安全 应用服务中间件 网络安全
实战经验分享:利用免费SSL证书构建安全可靠的Web应用
本文分享了利用免费SSL证书构建安全Web应用的实战经验,涵盖选择合适的证书颁发机构、申请与获取证书、配置Web服务器、优化安全性及实际案例。帮助开发者提升应用安全性,增强用户信任。
|
2月前
|
Kubernetes 安全 Devops
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
97 10
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
|
3月前
|
监控 前端开发 JavaScript
使用 MERN 堆栈构建可扩展 Web 应用程序的最佳实践
使用 MERN 堆栈构建可扩展 Web 应用程序的最佳实践
59 6
|
2月前
|
前端开发 安全 JavaScript
2025年,Web3开发学习路线全指南
本文提供了一条针对Dapp应用开发的学习路线,涵盖了Web3领域的重要技术栈,如区块链基础、以太坊技术、Solidity编程、智能合约开发及安全、web3.js和ethers.js库的使用、Truffle框架等。文章首先分析了国内区块链企业的技术需求,随后详细介绍了每个技术点的学习资源和方法,旨在帮助初学者系统地掌握Dapp开发所需的知识和技能。
2025年,Web3开发学习路线全指南
|
3月前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
55 7

热门文章

最新文章

  • 1
    Burp Suite Professional 2025.2 (macOS, Linux, Windows) - Web 应用安全、测试和扫描
    23
  • 2
    AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
    19
  • 3
    【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
    53
  • 4
    部署使用 CHAT-NEXT-WEB 基于 Deepseek
    291
  • 5
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    26
  • 6
    java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
    38
  • 7
    零基础构建开源项目OpenIM桌面应用和pc web- Electron篇
    28
  • 8
    【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
    20
  • 9
    FastAPI与Selenium:打造高效的Web数据抓取服务 —— 采集Pixabay中的图片及相关信息
    53
  • 10
    springSecurity学习之springSecurity过滤web请求
    59