使用EJS表单提交数据时所有值返回undefined问题求助
问题诊断与修复方案
核心问题:Express实例混用导致解析中间件未生效
你的代码中存在Express实例不一致的关键问题:在Server类构造函数里创建了类专属的this.app = express()实例,但在setRendering、configRoutes等方法中,却直接使用了全局的app变量(开头定义的const app = express();)。这导致你配置的表单解析中间件仅挂载到了全局app上,而实际运行的服务器是类内部的this.app实例,表单提交的x-www-form-urlencoded格式数据完全没被解析,最终req.body全为undefined。
具体修复步骤
1. 统一使用类内的Express实例
修改app.js,删除全局app变量,所有方法内均使用this.app替代原有的app:
// app.js 修改后 const express = require('express'); const mongoose = require('mongoose'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser') const loginRoutes = require('./routes/loginRoutes'); const signupRoutes = require('./routes/signupRoutes'); const logoutRoutes = require('./routes/logoutRoutes'); // 移除全局app定义:const app = express(); const path = require('path'); class Server { constructor() { this.app = express(); this.port = process.env.PORT || 3000; this.app.use(express.json()); this.path = path; this.setRendering(); this.configRoutes(); this.connectDB(); this.serverSetup(); } setRendering() { // 替换所有app为this.app this.app.use(bodyParser.urlencoded({ extended: true })); this.app.set('views', this.path.join(__dirname, './frontend/views')) this.app.set('view engine', 'ejs'); this.app.use(express.static(this.path.join(__dirname, './frontend/static'))); this.app.use(express.json()) } configRoutes() { this.app.get('/', (req, res) => { res.render('./index') }); this.app.use('/auth', loginRoutes, signupRoutes, logoutRoutes) this.app.get('*', (req, res) => { res.send('Page Not Found, check your spelling or routes'); }) } connectDB() { const URL = 'mongodb://localhost:27017/collection'; require('dotenv').config(); mongoose.connect(URL, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => { console.log(`Connected to MongoDB at the following URL: ${URL}`) }) .catch((err) => { console.error('Error connecting to MongoDB:', err); }); mongoose.connection.on('error', (err) => { console.error('MongoDB Connection Error:', err); }); mongoose.connection.once('open', () => { console.log('Connection established'); }); mongoose.connection.on('disconnected', () => { console.log('Successfully Disconnected from MongoDB'); }); process.on('SIGINT', () => { mongoose.connection.close(() => { console.log('Mongoose Connection automatically Disconnected due to process termination.'); process.exit(0); }); }); } serverSetup() { this.app.listen(this.port, () => { console.log(`server running at http://localhost:${this.port}/`) }) } } new Server();
2. 可选:简化中间件配置(使用Express内置解析器)
从Express 4.16.0开始,express.urlencoded已内置body-parser.urlencoded的功能,你可以替换掉bodyParser依赖,直接使用内置解析器,减少依赖包:
setRendering() { // 替换bodyParser为Express内置解析器 this.app.use(express.urlencoded({ extended: true })); this.app.set('views', this.path.join(__dirname, './frontend/views')) this.app.set('view engine', 'ejs'); this.app.use(express.static(this.path.join(__dirname, './frontend/static'))); this.app.use(express.json()) }
3. 验证修复效果
重启服务器后提交注册表单,此时req.body将正确获取到表单中的email、password等字段值,后续逻辑可正常执行。
额外确认项
- 表单
name属性与后端解构字段名完全匹配(你的代码已符合要求) - 表单
method为POST、action路径与路由配置一致(你的代码已符合要求)
内容的提问来源于stack exchange,提问作者user30069178
相关产品推荐
相关产品推荐

