Handlebars 简介

Handlebars 内置辅助函数:if、each、with

学会使用 Handlebars 内置的 if、unless、each、with 辅助函数,实现条件判断和列表循环。

🎯 引言

学会这篇文章,你将掌握 Handlebars 最常用的四个内置辅助函数:ifunlesseachwith。它们能让模板支持条件判断和列表循环,是实际开发中必不可少的工具。


🧱 if 条件判断

if 用于根据条件决定是否渲染某段内容。

index.js
const Handlebars = require('handlebars');

const template = `
{{#if isLogin}}
    <p>欢迎回来,{{username}}</p>
{{/if}}
`;

const compiled = Handlebars.compile(template);
const html = compiled({ isLogin: true, username: '小明' });

console.log(html);

输出:

<p>欢迎回来,小明</p>

如果需要 else 分支,可以用 {{else}}

{{#if isLogin}}
    <p>欢迎回来,{{username}}</p>
{{else}}
    <p>请先登录</p>
{{/if}}
Handlebars 的 if 只判断“真值”和“假值”。0''nullundefined[] 都会被视为假值。

✨ unless 反向判断

unlessif 的反向写法,只有当条件为假时才渲染内容。

{{#unless isLogin}}
    <p>你还没有登录</p>
{{/unless}}

它和下面的 if 写法效果一样:

{{#if isLogin}}
{{else}}
    <p>你还没有登录</p>
{{/if}}
unless 适合“如果不满足某条件就提示”的场景,代码比 if + else 更简洁。

💡 each 循环列表

each 用于遍历数组或对象。

遍历数组

index.js
const template = `
<ul>
    {{#each list}}
        <li>{{this}}</li>
    {{/each}}
</ul>
`;

const compiled = Handlebars.compile(template);
const html = compiled({ list: ['HTML', 'CSS', 'JavaScript'] });

console.log(html);

输出:

<ul>
    <li>HTML</li>
    <li>CSS</li>
    <li>JavaScript</li>
</ul>

each 内部,this 表示当前遍历项。

遍历对象数组

<ul>
    {{#each users}}
        <li>{{name}} - {{age}}岁</li>
    {{/each}}
</ul>

传入:

{ users: [{ name: '小明', age: 18 }, { name: '小红', age: 20 }] }

输出:

<ul>
    <li>小明 - 18岁</li>
    <li>小红 - 20岁</li>
</ul>

空数组处理

如果数组为空,可以用 {{else}} 显示提示:

<ul>
    {{#each users}}
        <li>{{name}}</li>
    {{else}}
        <li>暂无用户</li>
    {{/each}}
</ul>

⚖️ each 里的 @index 和 @key

遍历数组时,可以用 @index 获取当前索引:

<ul>
    {{#each list}}
        <li>{{@index}}. {{this}}</li>
    {{/each}}
</ul>

输出:

<ul>
    <li>0. HTML</li>
    <li>1. CSS</li>
    <li>2. JavaScript</li>
</ul>

遍历对象时,用 @key 获取当前键名:

<ul>
    {{#each user}}
        <li>{{@key}}: {{this}}</li>
    {{/each}}
</ul>

🧰 with 切换作用域

with 可以把当前上下文切换成指定对象,避免重复写前缀。

index.js
const template = `
{{#with user}}
    <p>姓名:{{name}}</p>
    <p>年龄:{{age}}</p>
{{/with}}
`;

const compiled = Handlebars.compile(template);
const html = compiled({
    user: { name: '小明', age: 18 }
});

console.log(html);

输出:

<p>姓名:小明</p>
<p>年龄:18</p>

进入 {{#with user}} 后,里面的 {{name}}{{age}} 就直接从 user 对象里取了。

如果 with 后面的值为假值(比如 nullundefined),内部内容不会渲染。

🧾 小节总结

  • if 用于条件渲染,支持 else 分支。
  • unlessif 的反向写法,条件为假时渲染。
  • each 用于遍历数组或对象,支持 else 处理空数据。
  • @index@key 分别用于获取数组索引和对象键名。
  • with 可以切换上下文,减少重复前缀。

❓ 知识问答

Q1:Handlebars 的 if 能写复杂表达式吗?

A:不能。Handlebars 主张“模板里不写复杂逻辑”,if 里只能写单个变量或简单值,不能写 a > ba && b 这类表达式。需要复杂判断时,可以在传入数据前计算好,或自定义 Helper。

Q2:each 里可以用 {{name}} 直接访问对象属性吗?

A:可以。遍历对象数组时,当前项就是上下文,{{name}} 会读取当前项的 name 属性。

Q3:with 和直接写 user.name 有什么区别?

A:功能一样,with 只是让代码更简洁。当某个对象属性很多时,用 with 可以减少重复前缀。

Q4:空数组在 each 里会报错吗?

A:不会。空数组会跳过渲染,可以用 {{else}} 给出友好提示。


🧪 小练习

给定以下数据,请编写 Handlebars 模板:

index.js
const data = {
    isVip: true,
    products: [
        { name: '苹果', price: 5 },
        { name: '香蕉', price: 3 }
    ]
};

// 请在这里编写模板
// 要求:
// 1. 如果 isVip 为 true,显示“VIP 专享”
// 2. 用 each 渲染 products 列表,显示名称和价格

🎉 恭喜你掌握了 Handlebars 的内置辅助函数!下一篇我们会学习 Partials,让模板可以像组件一样复用。