Handlebars 简介

Handlebars Partials:模板复用与模块化

学会使用 Partials 拆分和复用模板片段,掌握局部模板注册、传参和动态复用技巧。

🎯 引言

学会这篇文章,你将掌握 Handlebars 的 Partials 功能。它可以把重复的 HTML 片段抽成可复用的小模板,就像组件一样。当页面里出现多处相同结构时,Partials 能让你的模板更干净、更易维护。


🧱 什么是 Partials

Partials 是 Handlebars 里的“局部模板”或“模板片段”。你可以把公共部分抽出来,在多个地方引用。

比如每个用户卡片结构都一样,只是数据不同:

<div class="user-card">
    <h3>小明</h3>
    <p>18岁</p>
</div>

如果页面有 10 个用户,手写 10 次就不合适。我们可以把卡片结构做成 Partial,然后复用。


✨ 注册和使用 Partials

1. 注册 Partial

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

const cardTemplate = `
<div class="user-card">
    <h3>{{name}}</h3>
    <p>{{age}}岁</p>
</div>
`;

Handlebars.registerPartial('userCard', cardTemplate);

2. 在模板中引用

{{> userCard}}

3. 完整示例

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

// 注册 Partial
Handlebars.registerPartial('userCard', `
<div class="user-card">
    <h3>{{name}}</h3>
    <p>{{age}}岁</p>
</div>
`);

// 主模板
const template = `
<div class="user-list">
    {{#each users}}
        {{> userCard}}
    {{/each}}
</div>
`;

const compiled = Handlebars.compile(template);
const html = compiled({
    users: [
        { name: '小明', age: 18 },
        { name: '小红', age: 20 }
    ]
});

console.log(html);

输出:

<div class="user-list">
    <div class="user-card">
        <h3>小明</h3>
        <p>18岁</p>
    </div>
    <div class="user-card">
        <h3>小红</h3>
        <p>20岁</p>
    </div>
</div>
Partial 内部可以直接使用当前上下文的数据。在 each 里引用时,当前遍历项就是 Partial 的上下文。

💡 从文件加载 Partial

实际项目中,Partial 通常会放在单独的文件里,方便管理。

project/
├── partials/
│   └── user-card.hbs
├── index.js
└── template.hbs

partials/user-card.hbs

<div class="user-card">
    <h3>{{name}}</h3>
    <p>{{age}}岁</p>
</div>
index.js
// 引入文件系统模块和 Handlebars
const fs = require('fs');
const Handlebars = require('handlebars');

// 1. 从文件读取 Partial 模板内容
const userCard = fs.readFileSync('./partials/user-card.hbs', 'utf-8');
// 2. 注册名为 userCard 的 Partial
Handlebars.registerPartial('userCard', userCard);

// 3. 从文件读取主模板内容
const template = fs.readFileSync('./template.hbs', 'utf-8');
// 4. 编译主模板
const compiled = Handlebars.compile(template);

// 5. 传入数据渲染 HTML
const html = compiled({
    users: [
        { name: '小明', age: 18 },
        { name: '小红', age: 20 }
    ]
});

// 6. 输出最终 HTML
console.log(html);

⚡ Partial 传参

Partial 也可以接收参数,让复用更灵活。

{{> userCard name="小明" age=18}}

对应的 Partial 模板:

<div class="user-card">
    <h3>{{name}}</h3>
    <p>{{age}}岁</p>
</div>
带等号的参数是显式传参,name="小明" 传字符串,age=18 传数字。

🪤 常见踩坑

Partial 名称写错

{{> usercard}}

如果注册时叫 userCard,引用时也必须完全一致,包括大小写。

忘记注册 Partial

如果没有 registerPartial 就直接使用 {{> userCard}},运行时会报错:

Error: The partial userCard could not be found

🧾 小节总结

  • Partials 是 Handlebars 的局部模板,用于复用公共 HTML 片段。
  • 使用 Handlebars.registerPartial() 注册,用 {{> 名称}} 引用。
  • Partials 可以使用当前上下文数据,也可以显式传参。
  • 实际项目中,通常把 Partial 放在单独文件里,通过 fs.readFileSync 读取注册。

❓ 知识问答

Q1:Partials 和 each 有什么区别?

A:each 是循环语法,Partials 是模板复用。通常两者结合使用:each 负责遍历,Partial 负责渲染每一项的结构。

Q2:Partial 里能写 ifeach 吗?

A:可以。Partial 本质上就是一段 Handlebars 模板,支持所有 Handlebars 语法。

Q3:一个 Partial 可以在另一个 Partial 里引用吗?

A:可以。只要先注册好,Partial 之间可以互相嵌套。

Q4:Partial 传参时字符串和数字写法有什么区别?

A:name="小明" 表示字符串,age=18 表示数字。如果写成 age="18",在 Partial 里会被当成字符串处理。


🧪 小练习

请创建一个 partials/comment.hbs 文件,并编写主模板渲染评论列表:

partials/comment.hbs
<!-- 请在这里编写评论卡片的 Partial 模板 -->
index.js
const data = {
    comments: [
        { author: '小明', content: '写得很清楚!' },
        { author: '小红', content: '学到了,谢谢!' }
    ]
};

// 请在这里注册 Partial 并渲染列表

🎉 恭喜你掌握了 Handlebars 的 Partials!下一篇我们会学习自定义 Helpers,让模板拥有更强大的能力。