Mustache.js 模板引擎核心用法与外部模板加载实践
Mustache.js 作为 JavaScript 生态中经典的模板解决方案,采用"逻辑less"设计理念——模板层仅负责数据占位与结构呈现,所有业务判断均在数据准备阶段完成。
基础渲染机制
核心 API 为 Mustache.render(template, data),模板中通过 {{key}} 声明数据插槽:
<!-- 内联模板 -->
<script id="tmpl-greeting" type="text/template">
<h3>{{greetText}}, {{user.alias}}!</h3>
</script>
<script>
const source = document.getElementById('tmpl-greeting').innerHTML.trim();
// 数据驱动渲染
const output = Mustache.render(source, {
greetText: '欢迎回来',
user: { alias: 'Azure' }
});
</script>
上下文遍历与条件渲染
{{#segment}} 兼具双重语义:当绑定值为非空数组时触发遍历,为真值时则表现为条件渲染;{{^segment}} 对应取反逻辑:
<script id="tmpl-profile" type="text/template">
{{#hasAuth}}
<ul>
{{#skills}}
<li>{{lang}} — 熟练度{{level}}</li>
{{/skills}}
</ul>
{{/hasAuth}}
{{^hasAuth}}
<p>请先完成登录</p>
{{/hasAuth}}
</script>
数据层控制逻辑:
const dataset = {
hasAuth: true, // 真值显示技能列表
skills: [
{ lang: 'Rust', level: '精通' },
{ lang: 'TypeScript', level: '熟练' }
]
};
Lambda 与原始值渲染
除对象外,模板也可接收字符串、数值等原始类型,此时需用 {{.}} 指代当前上下文:
Mustache.render('当前计数: {{.}}', 42); // "当前计数: 42"
Mustache.render('{{.}}', ['a', 'b']); // 隐式转字符串 "a,b"
更实用的场景是传入函数实现动态计算:
const template = '生成时间: {{stamp}}';
const result = Mustache.render(template, {
stamp: () => new Date().toLocaleString('zh-CN')
});
外部模板文件加载方案
生产环境通常将模板抽离为独立文件,借助 jquery.mustache.js 扩展实现异步加载:
// 目录结构: templates/user-card.mustache
// 加载并渲染
$.Mustache
.load('templates/user-card.mustache')
.done(function () {
const html = $.Mustache.render('user-card', {
members: [
{ nickname: '林夕', role: '架构师' },
{ nickname: '南风', role: '全栈开发' }
]
});
document.getElementById('app').insertAdjacentHTML('beforeend', html);
});
封装通用加载器以提升复用性:
const TemplateLoader = {
cache: new Map(),
async fetch(tplName) {
if (this.cache.has(tplName)) {
return this.cache.get(tplName);
}
const res = await fetch(`templates/${tplName}.mustache`);
const text = await res.text();
this.cache.set(tplName, text);
return text;
},
async renderTo(selector, tplName, viewModel) {
const raw = await this.fetch(tplName);
const fragment = Mustache.render(raw, viewModel);
document.querySelector(selector).innerHTML = fragment;
}
};
// 调用
TemplateLoader.renderTo('#dashboard', 'report-table', {
rows: await fetchReportData()
});
模板安全与转义策略
默认 {{html}} 会对特殊字符做 HTML 实体编码,若需输出富文本使用三花括号:
<script id="tmpl-article" type="text/template">
<article>
<h1>{{title}}</h1>
<div>{{{richContent}}}</div> <!-- 信任源数据时启用 -->
</article>
</script>
建议配合 DOMPurify 等库对 {{{}}} 输入做净化处理,防范 XSS 风险。