使用 Node.Js、ExpressJs、MongoDB 和 VueJs 构建 Todo 应用程序 – 第 1 部分

2025-05-28

使用 Node.Js、ExpressJs、MongoDB 和 VueJs 构建 Todo 应用程序 – 第 1 部分

提示:最终结果将会是这样的。

在本教程中,我们将使用ExpressJs框架和MongoDB ,用 Node.Js 构建著名的待办事项应用程序。我忘了告诉你了吗?该应用程序将以 API 为中心,并且是全栈的 :)。

简而言之,如果您想学习如何使用 Node.Js 构建 API,那么您来对地方了。

现在你可以拿一瓶啤酒,让我们开始行动吧。

什么是 ExpressJs?

ExpressJs 简单来说,就是一个 Node.Js 的 Web 框架——摘自官方文档。Taylor Otwell(Laravel 的创始人)曾经说过:“开发者为开发者构建工具”。ExpressJs 正是为开发者而生,旨在简化 Node API。

什么是 MongoDB?

MongoDB 是一个 NoSQL 数据库。它完全面向文档。NoSQL 数据库允许您以 JSON 格式和任何格式存储数据。如果您想了解更多关于 MongoDB 的信息,我还写了一篇关于 MongoDB 的文章(链接

定义 Todo API

我喜欢先定义 API。下表列出了我们需要创建哪些 API 以及每个 API 的功能。

方法 小路 描述
得到 /待办事项 获取所有待办事项
得到 /todos/:id 获取一个待办事项
邮政 /待办事项 创建新的待办事项
/todos/:id 更新待办事项
删除 /todos/:id 删除新的待办事项

定义了我们的 API 后,让我们深入研究项目目录。

项目目录

当我告诉你,我们只需要不到 5 个文件和相对较少的代码行就能构建这个后端时,你可能会大吃一惊。没错!就是这么简单。我们就是这样做的 :)。

此时您应该创建一个项目文件夹,用于存放此应用程序后端部分的所有源代码。我将其命名为“我的后端”。您可以随意使用backend作为您的目录。它没有专利。:)

为了保持简单,当然,我们不应该为了追求简单而牺牲灵活性。我们将在您之前创建的目录中仅创建 4 个文件夹。

  1. config:包含应用程序的配置文件。
  2. 模型:这是我们的实体(Todo 数据结构)。
  3. 存储库:存储库在数据访问上添加了一个抽象层。您可以在此处详细了解此层的重要性。
  4. routes:路由是应用程序的入口。此文件夹包含一个文件,用于定义当用户访问特定路由时应该发生的情况。
├── config
├── models
├── respositories
└── routes
Enter fullscreen mode Exit fullscreen mode

您需要安装什么

  1. 你需要Node
  2. 您需要安装MongoDB

申请包

此应用依赖于几个软件包,并将使用 npm 进行安装。导航到刚刚创建的项目目录,并创建一个包含以下内容的package.json文件。

{
    "name": "node-todo",
    "version": "1.0.0",
    "description": "Simple todo application.",
    "main": "server.js",
    "author": "Samuel James",
    "scripts": {
        "build": "webpack",
        "start": "node app.js"
    },
    "dependencies": {
        "cookie-parser": "~1.4.4",
        "cors": "^2.8.5",
        "debug": "~2.6.9",
        "express": "~4.16.1",
        "http-errors": "~1.6.3",
        "jade": "~1.11.0",
        "mongoose": "^5.7.3",
        "morgan": "~1.9.1"
    }
}

Enter fullscreen mode Exit fullscreen mode

运行npm install安装依赖项。让我们继续定义应用程序所需的配置参数。

配置文件

我们将在文件中定义数据库连接 URL 和应用程序将监听的端口,config/Config.js如下所示:

//config/Config.js

module.exports = {
  DB: process.env.MONGO_URL ? process.env.MONGO_URL : 'mongodb://localhost:27017/todos',
  APP_PORT: process.env.APP_PORT ? process.env.APP_PORT : 80,
};

Enter fullscreen mode Exit fullscreen mode

在 中config/Config.js如果 已定义,则设置DB为 环境变量,否则默认为。我们对 也做了同样的操作MONGO_URLmongodb://localhost:27017/todosAPP_PORT

待办事项模型

模型是数据库中数据的对象表示。因此,让我们创建一个models/Todo.js包含以下内容的文件:

//models/Todo.js

const mongoose = require('mongoose');

const { Schema } = mongoose;

// Define schema for todo items
const todoSchema = new Schema({
  name: {
    type: String,
  },
  done: {
    type: Boolean,
  },
});

const Todo = mongoose.model('Todo', todoSchema);

module.exports = Todo;

Enter fullscreen mode Exit fullscreen mode

如果你注意到,我们使用 mongoose 来定义模式,对吧?Mongoose 是一个官方的 MongoDB 库,用于在 Node 中操作 MongoDB 数据库。在结构中,我定义了namedone

name:这是待办事项的名称。我们将其定义为字符串。例如,“我打算下午 3 点前去游泳”
。done:待办事项的状态,布尔值。如果待办事项仍处于待处理状态,则其值为 false。

现在,我们将创建一个待办事项存储库。

存储库

我喜欢将存储库视为一种抽象数据访问的策略。当我在一个项目中切换到新的数据存储时,这种模式让我免于繁重的重构,这让我对它产生了浓厚的兴趣。它可以帮助项目解耦,并减少代码重复。这里有一篇关于这种模式的有趣文章,推荐你阅读。

也就是说,创建一个文件repositories/TodoRepository.js作为:

//repositories/TodoRepository

const Todo = require('../models/Todo');

class TodoRepository {

  constructor(model) {
    this.model = model;
  }

  // create a new todo
  create(name) {
    const newTodo = { name, done: false };
    const todo = new this.model(newTodo);

    return todo.save();
  }

  // return all todos

  findAll() {
    return this.model.find();
  }

  //find todo by the id
  findById(id) {
    return this.model.findById(id);
  }

    // delete todo
  deleteById(id) {
    return this.model.findByIdAndDelete(id);
  }

  //update todo
  updateById(id, object) {
    const query = { _id: id };
    return this.model.findOneAndUpdate(query, { $set: { name: object.name, done: object.done } });
  }
}

module.exports = new TodoRepository(Todo);

Enter fullscreen mode Exit fullscreen mode

定义完成后TodoRepository.js,我们来创建待办事项路线。

路线

每个 Web 应用至少都有一个入口点。Web 应用中的路由更像是在说:“嘿,Jackson,当我要求你这个时,你就给我那个”。我们的应用也是如此,我们会定义用户需要访问哪些 URL 才能获得特定结果或触发特定操作。

在这种情况下,我们希望用户能够对待办事项执行创建、读取、更新和删除(CRUD)操作。

现在,您知道“routes”的作用了,请创建routes/Routes.js文件并输入以下代码:

const express = require('express');

const app = express.Router();
const repository = require('../respositories/TodoRepository');

// get all todo items in the db
app.get('/', (req, res) => {
  repository.findAll().then((todos) => {
    res.json(todos);
  }).catch((error) => console.log(error));
});

// add a todo item
app.post('/', (req, res) => {
  const { name } = req.body;
  repository.create(name).then((todo) => {
    res.json(todo);
  }).catch((error) => console.log(error));
});

// delete a todo item
app.delete('/:id', (req, res) => {
  const { id } = req.params;
  repository.deleteById(id).then((ok) => {
    console.log(ok);
    console.log(`Deleted record with id: ${id}`);
    res.status(200).json([]);
  }).catch((error) => console.log(error));
});

// update a todo item
app.put('/:id', (req, res) => {
  const { id } = req.params;
  const todo = { name: req.body.name, done: req.body.done };
  repository.updateById(id, todo)
    .then(res.status(200).json([]))
    .catch((error) => console.log(error));
});
module.exports = app;

Enter fullscreen mode Exit fullscreen mode

首先,您希望用户获取数据库中所有待办事项的列表,因此我们定义了一个路由(/all),该路由接受获取请求并在成功时返回待办事项的 JSON 对象。

我们的用户喜欢获取物品以及存储新物品,因此我们添加了一个用于创建新待办事项的路由。它接受 post 请求。
当 A 先生向路由发出 post 请求 ( /add ) 时,数据库中就会创建一个新的待办事项。

待办事项完成后,我们希望用户能够将其标记为已完成。为此,首先必须知道用户想要将哪个事项标记为已完成。因此,我们定义了一个“更新路由”,其路由参数是待更新事项的 ID。

服务器文件

定义了应用程序所需的所有路由后,就该创建一个入口文件了,它是运行我们项目的主文件。

在项目根文件夹中,创建一个app.js文件并使用以下内容更新其内容:

//app.js

const createError = require('http-errors');
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors')

const config = require('./config/Config');

const routes = require('./routes/Routes');

const app = express();

mongoose.connect(config.DB, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

app.use(cors());  //enable cors

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/todos', routes);

// catch 404 and forward to error handler
app.use((req, res, next) => {
  next(createError(404));
});

// error handler
app.use((err, req, res) => {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

app.listen(config.APP_PORT); // Listen on port defined in environment


module.exports = app;

Enter fullscreen mode Exit fullscreen mode

我们要求:

  • Express JS

  • morgan - Node 的日志中间件

  • path -用于处理文件和目录的包

  • mongoose -用于 MongoDB 的软件包

  • body-parser -一个 正文解析中间件

我们将应用设置为监听 config/Config.js 中设置的端口我们还定义了它使用routes/Routes.js中定义的路由,并在其前面加上todos前缀。

最后,您的目录结构应如下所示:

├── app.js
├── config
│   └── Config.js
├── models
│   └── Todo.js
├── package-lock.json
├── package.json
├── respositories
│   └── TodoRepository.js
└── routes
    └── Routes.js
Enter fullscreen mode Exit fullscreen mode

要启动应用程序,请导航到项目根目录并运行:

npm start
Enter fullscreen mode Exit fullscreen mode

让我们创建一个新的待办事项

$ curl -H "Content-Type: application/json" -X POST -d '{"name":"Going Shopping"}' http://localhost/todos

{"__v":0,"name":"Going Shopping","done":false,"_id":"5a6365a39a2e56bc54000003"}
Enter fullscreen mode Exit fullscreen mode

获取所有待办事项

$ curl  http://localhost/todos

[{"_id":"5a6365a39a2e56bc54000003","name":"Doing Laundry","done":false,"__v":0},{"_id":"5a6366039a2e56bc54000004","name":"Going Shopping","done":false,"__v":0}]

Enter fullscreen mode Exit fullscreen mode

搭建完成了吗?快来看看第二部分吧。

在此处获取源代码

文章来源:https://dev.to/abiodunjames/build-a-todo-app-with-nodejs-expressjs-mongodb-and-vuejs--part-1--29n7
PREV
为什么选择 Docker?用 Docker 创建多容器应用程序
NEXT
JS 面试题