Handlebars 自定义 Helpers:扩展模板能力
🎯 引言
学会这篇文章,你将掌握 Handlebars 的 自定义 Helper。Handlebars 的模板里不能写复杂表达式,但现实世界常有格式化、判断、计算等需求。通过 Helper,你可以把这些逻辑封装成可复用的函数,在模板里像调用 API 一样使用。
🧱 为什么需要自定义 Helper
来看一个常见需求:把价格格式化成“¥xx.xx”。
模板里不能写 {{price.toFixed(2)}},因为 Handlebars 不支持这种表达式。解决方案是写一个 Helper:
Handlebars.registerHelper('formatPrice', function (price) {
return '¥' + price.toFixed(2);
});
模板里这样用:
<p>价格:{{formatPrice price}}</p>
传入 { price: 19.9 },输出:
<p>价格:¥19.90</p>
✨ 注册一个简单的 Helper
const Handlebars = require('handlebars');
// 注册 Helper
Handlebars.registerHelper('uppercase', function (str) {
return str.toUpperCase();
});
// 使用 Helper
const template = '<p>{{uppercase name}}</p>';
const compiled = Handlebars.compile(template);
const html = compiled({ name: 'hello' });
console.log(html);
输出:
<p>HELLO</p>
Helper 的第一个参数是模板中传入的值,后面可以继续接更多参数。
💡 带多个参数的 Helper
Handlebars.registerHelper('join', function (arr, separator) {
return arr.join(separator);
});
模板:
<p>标签:{{join tags "、"}}</p>
传入:
{ tags: ['前端', 'Handlebars', '模板引擎'] }
输出:
<p>标签:前端、Handlebars、模板引擎</p>
⚖️ 实现比较运算 Helper
Handlebars 原生的 if 不支持表达式,我们可以写一个 eq Helper 来判断是否相等:
Handlebars.registerHelper('eq', function (a, b) {
return a === b;
});
模板:
{{#if (eq status "success")}}
<p>操作成功</p>
{{/if}}
传入:
{ status: 'success' }
输出:
<p>操作成功</p>
() 包裹 Helper 调用,可以把结果作为另一个 Helper(如 if)的参数。🛠 常用的自定义 Helper 示例
1. 格式化日期
Handlebars.registerHelper('formatDate', function (date) {
const d = new Date(date);
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
});
2. 判断数组是否为空
Handlebars.registerHelper('isEmpty', function (arr) {
return !arr || arr.length === 0;
});
3. 计算索引加一
Handlebars.registerHelper('addOne', function (index) {
return index + 1;
});
模板:
<ul>
{{#each list}}
<li>{{addOne @index}}. {{this}}</li>
{{/each}}
</ul>
🪤 Helper 里要注意的 this
在 Helper 函数里,this 指向当前模板上下文。如果在块级 Helper 里使用,要注意上下文变化。
Handlebars.registerHelper('showContext', function () {
console.log(this);
});
一般情况下,简单 Helper 不会用到 this,了解即可。
🧾 小节总结
- 自定义 Helper 用于扩展模板能力,处理格式化、比较、计算等逻辑。
- 使用
Handlebars.registerHelper()注册 Helper。 - Helper 可以接受一个或多个参数。
- 用
()可以把 Helper 结果作为另一个 Helper 的参数。
❓ 知识问答
Q1:Handlebars 模板里能写 {{a + b}} 吗?
A:不能。Handlebars 不支持表达式,需要用自定义 Helper 实现,比如 {{add a b}}。
Q2:Helper 和 Partial 有什么区别?
A:Helper 是一段 JavaScript 逻辑,返回一个值;Partial 是一段模板片段,返回一段 HTML。Helper 处理数据,Partial 复用结构。
Q3:自定义 Helper 可以返回 HTML 吗?
A:可以,但返回的字符串默认会被转义。如果想输出原始 HTML,需要用 new Handlebars.SafeString(html) 包裹。
Q4:Helper 命名有什么规范吗?
A:建议用驼峰命名,避免和内置 Helper 重名,比如不要用 if、each 等内置名称。
🧪 小练习
请编写一个 formatDate Helper,并渲染以下数据:
const data = {
createdAt: '2024-10-01T08:00:00.000Z'
};
// 请在这里注册 formatDate Helper
// 要求:把日期格式化为 YYYY-MM-DD
🎉 恭喜你掌握了 Handlebars 的自定义 Helper!下一篇我们会学习预编译和运行时,了解如何在生产环境中更高效地使用 Handlebars。
