You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+MongoDB+hbs基于async-await的CRUD更新删除操作实现咨询

运行前置准备
  • 需提前安装依赖包:express、mongoose、express-handlebars、method-override(浏览器form默认仅支持GET/POST请求,该中间件用于支持PUT/DELETE请求,多数更新删除报错都是漏装该依赖导致)
  • 本地需启动MongoDB服务
1. Mongoose 数据模型定义

以Todo业务场景为例,代码路径models/Todo.js:

const mongoose = require('mongoose');

const todoSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  content: {
    type: String,
    required: true
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Todo', todoSchema);
2. Express 服务及路由配置

代码路径app.js:

const express = require('express');
const mongoose = require('mongoose');
const exphbs = require('express-handlebars');
const methodOverride = require('method-override');
const Todo = require('./models/Todo');
const app = express();

// 连接MongoDB
mongoose.connect('mongodb://localhost:27017/todoDB', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('MongoDB连接成功'))
.catch(err => console.log(err));

// 配置handlebars模板引擎
app.engine('hbs', exphbs.engine({ extname: 'hbs' }));
app.set('view engine', 'hbs');

// 全局中间件配置
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method')); // 解析PUT/DELETE请求的核心配置

// GET请求:查询所有数据渲染首页
app.get('/', async (req, res) => {
  // .lean()将mongoose文档对象转为普通JS对象,否则hbs无法读取属性
  const todos = await Todo.find().lean();
  res.render('index', { todos });
});

// POST请求:新增数据
app.post('/todos', async (req, res) => {
  await Todo.create(req.body);
  res.redirect('/');
});

// GET请求:跳转编辑页
app.get('/todos/edit/:id', async (req, res) => {
  const todo = await Todo.findById(req.params.id).lean();
  res.render('edit', { todo });
});

// PUT请求:更新数据
app.put('/todos/:id', async (req, res) => {
  await Todo.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
    runValidators: true // 开启字段校验,避免非法数据入库
  });
  res.redirect('/');
});

// DELETE请求:删除数据
app.delete('/todos/:id', async (req, res) => {
  await Todo.findByIdAndDelete(req.params.id);
  res.redirect('/');
});

const PORT = 3000;
app.listen(PORT, () => console.log(`服务运行在 http://localhost:${PORT}`));
3. Handlebars 模板文件

3.1 首页模板 路径views/index.hbs

<h1>Todo列表</h1>
<!-- 新增表单 -->
<form action="/todos" method="POST">
  <div>
    <label>标题:</label>
    <input type="text" name="title" required>
  </div>
  <div>
    <label>内容:</label>
    <textarea name="content" required></textarea>
  </div>
  <button type="submit">新增</button>
</form>
<hr>
<!-- 数据列表 -->
{{#each todos}}
  <div style="border:1px solid #eee; padding:12px; margin:10px 0;">
    <h3>{{title}}</h3>
    <p>{{content}}</p>
    <p>创建时间:{{createdAt}}</p>
    <a href="/todos/edit/{{_id}}">编辑</a>
    <!-- 删除表单 -->
    <form action="/todos/{{_id}}?_method=DELETE" method="POST" style="display:inline;margin-left:10px;">
      <button type="submit" onclick="return confirm('确定删除吗?')">删除</button>
    </form>
  </div>
{{/each}}

3.2 编辑页模板 路径views/edit.hbs

<h1>编辑Todo</h1>
<form action="/todos/{{todo._id}}?_method=PUT" method="POST">
  <div>
    <label>标题:</label>
    <input type="text" name="title" value="{{todo.title}}" required>
  </div>
  <div>
    <label>内容:</label>
    <textarea name="content" required>{{todo.content}}</textarea>
  </div>
  <button type="submit">保存修改</button>
  <a href="/" style="margin-left:10px;">取消</a>
</form>
常见报错修复方案
  • 请求404/方法不允许:检查是否配置了method-override中间件,表单的_method参数拼写是否正确
  • 模板页变量不显示:查询数据时是否加了.lean(),mongoose返回的文档对象hbs无法直接读取
  • 更新时字段校验失效:findByIdAndUpdate方法是否加了runValidators: true配置

内容的提问来源于stack exchange,提问作者neo kiyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 18:54:07