在 EJS 模板中,layout() 函数不支持直接传参;若需跨多级 partial(如页面 → 表单布局 → 页眉组件)传递变量(如 progress),必须统一使用 include() 并显式透传数据,避免 ReferenceError。
在 ejs 模板中,`layout()` 函数不支持直接传参;若需跨多级 partial(如页面 → 表单布局 → 页眉组件)传递变量(如 `progress`),必须统一使用 `include()` 并显式透传数据,避免 referenceerror。
EJS 的 layout() 是一个特殊辅助函数(常由 Express-EJS 中间件或 ejs-mate 等库提供),其设计初衷仅用于指定外层布局文件路径,不接受第二参数传入局部变量。因此,你在顶层使用 时,{ progress: 10 } 实际被忽略,导致下层 formPartial.ejs 中无法访问 progress,进而引发 ReferenceError: progress is not defined。
✅ 正确做法:全程使用 替代 layout() 实现可控的数据流透传。所有层级均需显式接收并向下传递所需变量。
✅ 推荐重构方案(三层嵌套示例)
1. 顶层页面(如 views/form/running-habits.ejs)
不再调用 layout(),改用 include() 引入表单布局,并传入 progress:
<%- include('../form/formPartial.ejs', { progress: 10 }) %>
<div class="container pt-5">
<div class="row">
<div class="col">
<h2>Running habits and goals</h2>
</div>
</div>
<div class="row">
<div class="col">
<p>Get started by telling Fittir about your running habits and goals.</p>
</div>
</div>
</div>
<div class="container mt-auto">
<div class="row">
<div class="col">
<p>Time to complete: 5 minutes</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill10340" title="arcgis-js"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20e352aa140.jpg" alt="arcgis-js" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill10340" title="arcgis-js">arcgis-js</a>
<p>提供 ArcGIS Maps SDK for JavaScript 开发辅助,涵盖 2D/3D 地图视图、图层管理、数据可视化、空间分析等功能模块的参考和示例指导。</p>
</div>
<a href="/xiazai/skill10340" title="arcgis-js" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
</div>
</div>
</div>2. 中间层布局(views/form/formPartial.ejs)
接收 progress,并继续透传给 formHeader 和 formFooter:
<%- include('../layouts/form_boilerplate.ejs', { progress: progress }) %>
<form class="form" action="" method="POST">
<%- include('../partials/formHeader.ejs', { progress: progress }) %>
<div class="form-body d-flex flex-column">
<%- body %>
<div class="container mt-auto">
<%- include('../partials/formFooter.ejs') %>
</div>
</div>
</form>⚠️ 注意:body 是 Express-EJS 默认提供的变量(代表 res.render() 渲染的内容体),它本身不携带 progress,因此若需在 body 区域内使用 progress,也应在 res.render() 时一并传入(如 res.render('form/running-habits', { progress: 10 })),并在顶层模板中通过 显式传递。
3. 底层组件(views/partials/formHeader.ejs)
安全使用 progress(已由上层传入):
<header>
<div class="container">
<div class="row">
<div class="col">
<a class="navbar-brand" href="/"><img src="/logos/logo-primary.svg" class="logo-primary" alt="EJS 中多层模板嵌套时正确传递变量的完整指南" ></a>
</div>
<div class="col">
<div class="row">
<div class="progress mt-2 px-0">
<div class="progress-bar"
role="progressbar"
aria-valuenow="<%= progress %>"
aria-valuemin="0"
aria-valuemax="100"
style="width: <%= progress %>%">
</div>
</div>
</div>
<div class="row">
<div class="col px-1">
<p><%= progress %>% completed</p>
</div>
</div>
</div>
</div>
</div>
</header>? 关键注意事项
- 不要混用 layout() 和变量透传逻辑:layout() 是语义化布局钩子,非数据通道;依赖它传参是常见误区。
- 路径需准确:include() 路径基于当前文件位置,建议统一使用相对路径(如 ../partials/xxx.ejs)并确保文件存在。
- 变量作用域严格受限:EJS 中每个 include 创建独立作用域,父级变量不会自动继承,必须显式 { key: value } 传入。
- 调试技巧:可在任意 partial 开头添加 快速验证变量是否到达。
✅ 总结
EJS 多层 partial 间传递变量的核心原则是:“谁需要,谁接收;谁使用,谁透传”。放弃对 layout() 的参数幻想,全面采用 构建清晰、可维护、可调试的模板数据流。这样不仅能解决 progress is not defined 错误,也为后续扩展(如动态进度计算、国际化文案)打下坚实基础。

















