Node.js-EJS实现单文件按需引入HTML片段的方案咨询
实现单个EJS文件按需导出HTML片段的方案
核心思路
把所有HTML片段集中放在一个EJS文件中,通过标识匹配的方式按需渲染对应内容,既不用在JS里写冗长的HTML字符串,也无需创建数百个独立的小模板文件。下面提供两种可行的实现方式:
方式一:在EJS模板内用条件/映射渲染
1. 创建统一的HTML片段模板(如perk-info.ejs)
用对象映射的方式组织所有perk的HTML片段,键为perk的唯一标识,值为返回HTML的函数:
<% // 定义所有perk的HTML片段映射 const perkHtmlMap = { 'unnerving-presence': () => { %> <div class="perk-card"> <h3>Unnerving Presence</h3> <div class="perk-desc"> <p>你的气场会让逃生者的技能校验难度提升,成功校验的判定区域缩小20%。</p> <p>当逃生者在你的恐惧范围内时,他们的技能触发时间延长10%。</p> </div> </div> <% }, 'brutal-strength': () => { %> <div class="perk-card"> <h3>Brutal Strength</h3> <div class="perk-desc"> <p>破坏发电机、钩子、板子的速度提升15%。</p> <p>每次完成破坏动作后,获得2秒的3%移动速度加成。</p> </div> </div> <% }, 'agitation': () => { %> <div class="perk-card"> <h3>Agitation</h3> <div class="perk-desc"> <p>携带逃生者时移动速度提升8%,恐惧范围扩大16米。</p> <p>逃生者的挣扎速度降低15%。</p> </div> </div> <% } // 继续添加其他perk的片段 } %> <!-- 根据传入的perkId渲染对应片段 --> <% if (perkHtmlMap[perkId]) { %> <% perkHtmlMap[perkId]() %> <% } else { %> <div class="perk-card">暂无技能信息</div> <% } %>
2. 调整killerdata.js的结构
把perk的名称和标识分开存储,方便后续匹配:
exports.trapper = { name:"Evan McMillan", moveSpeed:"115% | 4.6m/s", terrorRadius:"32 metres", voiceActor:"Filip Ivanovic (BHVR)", perk1Id:"unnerving-presence", perk1Name:"Unnerving Presence", perk2Id:"brutal-strength", perk2Name:"Brutal Strength", perk3Id:"agitation", perk3Name:"Agitation" };
3. 后端传递标识到主模板(app.js)
const killerData = require(__dirname + '/js/killerdata.js'); app.get('/killer/:killerid', function(req, res){ const killerid = req.params.killerid; const killerInfo = killerData[killerid]; res.render('killer', { killerid: killerid, killerName: killerInfo.name, killerMoveSpeed: killerInfo.moveSpeed, killerTerrorRadius: killerInfo.terrorRadius, killerVoiceActor: killerInfo.voiceActor, // 传递perk的标识和名称 perk1: { id: killerInfo.perk1Id, name: killerInfo.perk1Name }, perk2: { id: killerInfo.perk2Id, name: killerInfo.perk2Name }, perk3: { id: killerInfo.perk3Id, name: killerInfo.perk3Name } }); });
4. 主模板(killer.ejs)引入片段
通过EJS的include语法,传入对应的perk标识即可渲染:
<div class="killer-perks-container"> <div class="perk-item"> <h4><%= perk1.name %></h4> <% include ./perk-info.ejs { perkId: perk1.id } %> </div> <div class="perk-item"> <h4><%= perk2.name %></h4> <% include ./perk-info.ejs { perkId: perk2.id } %> </div> <div class="perk-item"> <h4><%= perk3.name %></h4> <% include ./perk-info.ejs { perkId: perk3.id } %> </div> </div>
方式二:后端预渲染HTML片段
如果希望主模板更简洁,可以在后端提前渲染好HTML字符串,再传递给主模板:
1. 后端添加预渲染逻辑(app.js)
const ejs = require('ejs'); const path = require('path'); // 封装渲染perk片段的函数 async function renderPerkHtml(perkId) { return ejs.renderFile( path.join(__dirname, 'views/perk-info.ejs'), { perkId }, { async: true } ); } app.get('/killer/:killerid', async function(req, res){ const killerid = req.params.killerid; const killerInfo = killerData[killerid]; // 预渲染每个perk的HTML const perk1Html = await renderPerkHtml(killerInfo.perk1Id); const perk2Html = await renderPerkHtml(killerInfo.perk2Id); const perk3Html = await renderPerkHtml(killerInfo.perk3Id); res.render('killer', { killerid: killerid, killerName: killerInfo.name, killerMoveSpeed: killerInfo.moveSpeed, killerTerrorRadius: killerInfo.terrorRadius, killerVoiceActor: killerInfo.voiceActor, perk1Name: killerInfo.perk1Name, perk1Html: perk1Html, perk2Name: killerInfo.perk2Name, perk2Html: perk2Html, perk3Name: killerInfo.perk3Name, perk3Html: perk3Html }); });
2. 主模板直接输出预渲染的HTML
注意用<%-标签输出原始HTML,避免EJS转义标签:
<div class="perk-item"> <h4><%= perk1Name %></h4> <%- perk1Html %> </div>
关键注意事项
- 所有HTML片段的标识要保持统一(比如全小写+连字符),避免拼写错误
- 用
<%-输出HTML时,要确保内容是可信的,防止XSS风险 - 如果后续perk数量持续增加,可以把
perkHtmlMap拆分到单独的JS模块中,再在EJS里引入
内容的提问来源于stack exchange,提问作者reeser00
相关产品推荐
相关产品推荐

