
EJS 模板中引用未传递的变量(如 donors)会触发 ReferenceError,导致页面白屏;根本解决方法是在所有 res.render() 调用中统一提供该变量(即使为空数组或默认值),确保模板逻辑安全执行。
如何解决 ejs 模板中因变量未定义导致页面无法渲染的问题 —— ejs 模板中引用未传递的变量(如 `donors`)会触发 `referenceerror`,导致页面白屏;根本解决方法是在所有 `res.render()` 调用中统一提供该变量(即使为空数组或默认值),确保模板逻辑安全执行。
在 Express + EJS 应用中,模板渲染失败常源于变量契约不一致:EJS 文件(如 donors.ejs)假定 donors 变量始终存在并可访问,但后端路由却在某些路径下未传入该变量。正如错误所示:
ReferenceError: donors is not defined
at eval (eval at compile (.../node_modules/ejs/lib/ejs.js:662:12), <anonymous>:98:10)这明确指出:第 98 行 0) { %> 尝试读取未声明的 donors,JavaScript 引擎直接抛出 ReferenceError(而非 undefined 的宽松判断),中断整个模板渲染流程。
? 根本原因分析
观察您的三处 GET 路由:
- ✅
/donors(带数据库查询):正确传入{ donors: defaultDonors, ... } - ❌
/donors(空渲染):res.render('donors.ejs', {})→donors完全缺失 - ❌
/views/donors.ejs:res.render('donors.ejs', {})→ 同样缺失donors
⚠️ 注意:Express 不允许为同一路径注册多个同类型(GET)路由——后注册的会覆盖前一个。因此您实际生效的很可能是最后一个空渲染路由,导致所有 /donors 请求都因缺少 donors 而崩溃。
✅ 正确解决方案:强制变量“保底”
所有 res.render() 必须显式提供 donors,推荐使用空数组 [](语义清晰、.length 安全、forEach 可安全调用):
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
// ✅ 修正后的 GET 路由(移除重复注册,仅保留一个健壮版本)
app.get('/donors', async (req, res) => {
try {
const bloodTypesResult = await db.query('SELECT DISTINCT blood_type FROM donors');
const bloodTypes = bloodTypesResult.rows;
const citiesResult = await db.query('SELECT * FROM city');
const cities = citiesResult.rows;
const defaultDonorsResult = await db.query('SELECT * FROM donors LIMIT 12');
const defaultDonors = defaultDonorsResult.rows;
// ✅ 关键:始终传入 donors(即使为空)
res.render('donors.ejs', {
blood_type: bloodTypes,
city: cities,
donors: defaultDonors, // ← 确保存在
getBloodTypeText,
getCompatibleBloodTypes
});
} catch (error) {
console.error('Error fetching data:', error);
res.status(500).send('Internal Server Error');
}
});同时,彻底删除冗余路由:
// ❌ 删除这两项(它们不仅无效,还会引发冲突和安全隐患)
// app.get('/donors', (req, res) => { res.render('donors.ejs', {}); });
// app.get('/views/donors.ejs', (req, res) => { res.render('donors.ejs', {}); });? 安全增强建议:在 EJS 中也可做双重防护(非必需,但更健壮):
<% if (typeof donors !== 'undefined' && donors && donors.length > 0) { %> <% donors.forEach(donor => { %> <!-- 渲染逻辑 --> <% }); %> <% } else { %> <p class="text-muted">No donors available.</p> <% } %>但更推荐在服务端统一兜底,保持模板简洁。
? 总结与最佳实践
-
变量即契约:EJS 模板依赖的每个变量,必须在每次
res.render()时显式传入; -
默认值优先:对数组类变量(如
donors)使用[],对象类用{},布尔类用false,避免undefined; - 路由去重:同一 HTTP 方法 + 路径只能有一个处理函数,重复注册会导致不可预期行为;
-
开发期验证:可在模板顶部添加调试输出
快速检查传入变量; -
错误友好提示:生产环境应捕获
ReferenceError并返回友好的 500 页面,而非堆栈暴露。
遵循以上原则,即可彻底规避 is not defined 类型错误,保障 EJS 页面稳定、可靠地渲染。

















