给前端开发者的HTML模板设计模式,别再用字符串拼接了
从字符串拼接的泥潭里爬出来
如果你写过几年前端,大概率见过这样的代码:`'<div class="card"><h3>' + title + '</h3><p>' + desc + '</p></div>'`。一开始觉得挺爽,逻辑简单,想加什么就拼什么。直到某天需求变动,要加条件渲染、要循环输出列表、要处理用户输入的特殊字符——字符串拼接瞬间变成一场噩梦。引号嵌套地狱、XSS 漏洞、可读性归零,维护的人恨不得把键盘摔了。
其实我们早就有了更好的选择:HTML 模板设计模式。不是让你去学什么重型框架,而是从思维层面转变:把 HTML 当作数据结构的映射,而不是字符串的堆砌。
模板的本质:分离结构与逻辑
传统拼接方式最大的问题,是把“数据”和“展示”揉成一团。每当你想改个按钮样式,或者调整某个字段的位置,必须从一大段字符串里找到对应位置,小心翼翼地挪动。而模板设计模式的核心,是让 HTML 结构保持完整,只在需要动态变化的地方留出“插槽”。
最简单的实践就是使用 ES6 模板字符串。不需要任何库,原生就能写:
const card = ({ title, desc, tag }) => `
<div class="card">
<h3>${title}</h3>
<p>${desc}</p>
${tag ? `<span class="tag">${tag}</span>` : ''}
</div>
`;
看起来只是换了种写法?不,关键区别在于:模板结构是静态可视的——你能一眼看出整个 DOM 长什么样,条件分支通过 `${}` 内嵌表达式表达,而不是把整段 HTML 拆成无数个加号。这已经是从“拼字符串”到“写模板”的第一步。
进阶模式:再也不用担心引号和转义
当你的页面出现循环列表时,字符串拼接会逼你写出令人窒息的三层嵌套循环加数组 join。模板设计模式会用更优雅的方式处理:要么用 map 返回模板数组,要么用模板内部的循环语法(如 handlebars 的 `{{#each}}`)。即便不用框架,我们也可以用 `map` 加 `join('')` 来保持清晰:
const list = items.map(item => `
<li class="item-${item.type}">
<span>${item.name}</span>
<small>${formatDate(item.createdAt)}</small>
</li>
`).join('');
注意这里我们把 `formatDate` 这类纯函数直接嵌入模板表达式,让数据在进入展示层之前就完成格式化,模板里只关心“放什么”,不关心“怎么算”。
再进一步,如果你希望彻底摆脱手动拼接的脆弱感,可以试试组件函数模式——每个 UI 块就是一个纯函数,接收数据、返回 HTML。这其实是现代前端框架的雏形,但即便不用 React/Vue,你也可以自己实现:
function Button({ text, onClick }) {
return `<button class="btn" data-action="${onClick}">${escapeHtml(text)}</button>`;
}
function Modal({ title, content }) {
return `
<div class="modal-overlay">
<div class="modal">
<h2>${title}</h2>
<div>${content}</div>
${Button({ text: '关闭', onClick: 'closeModal' })}
</div>
</div>
`;
}
这种模式让模板像积木一样可组合。你要改按钮样式,只改 Button 函数;要加新的弹窗,直接调用 Modal 并传入不同的 content。比起全局搜索字符串片段,这种局部封装能极大提升重构效率。
警惕安全陷阱:永远记得转义
模板设计模式还有个隐形福利:如果设计得当,可以强制进行 HTML 转义。比如统一封装一个 `escapeHtml` 函数,并在模板渲染入口对所有插值变量调用,从根源杜绝 XSS。如果你手写拼接字符串,十有八九会忘记转义某些用户输入字段。而模板 + 默认转义的组合(许多模板引擎自带)能让你少焦虑很多。
同时,为了照顾老旧浏览器或不愿引入构建工具的朋友,也可以选择轻量级字符串模板库(如 `lodash.template`)。本质上它们的思路和上面一样:用模板语法代替手写拼接,用预编译提升性能。
从“能跑”走向“可维护”
这篇文章不是让你去批判字符串拼接——毕竟有些极简场景用它也没问题。但当你面对稍微复杂的页面逻辑时,请停下来想一想:这段 HTML 是否在生成过程中丢失了结构感?后期别人(或三个月后的自己)能否一眼看懂条件分支和循环放在哪里?
HTML 模板设计模式真正的价值,在于它逼你把“页面长什么样”和“数据怎么处理”分开。这也是无数优秀架构的底层逻辑。告别胡子拉碴的拼字符串代码,让自己的模板像页面设计稿一样干净整齐,你会在每次维护时都感谢自己当初的选择。
管理员
黑卡会员