可视化内容片段 — 模板 visual-content-fragments-templates
- 适用对象:
- Experience Manager as a Cloud Service
在Adobe Experience Manager (AEM) as a Cloud Service中,HTML模板可用于可视化内容片段,并以HTML格式交付它们。
可视化内容片段和可视化内容片段图形作业当前处于“有限可用”状态。
HTML模板允许您控制内容片段的显示方式。 您可以在选择的代码编辑器中创建HTML模板,然后上传这些模板并将其分配给AEM中的内容片段模型。 使用Handlebars.js的内容占位符允许将模板映射到内容片段模型中的数据类型。 将模板分配给模型后,即可与基于模型的任何内容片段一起使用,以可视化片段或将其作为HTML格式的模块化体验交付到任何渠道,例如Web、电子邮件、移动应用程序或其他渠道。
本文介绍了如何使用Handlebars语法创建自定义HTML模板以呈现可视化内容片段。
创建模板后,您可以:
您将学习的内容 what-you-will-learn
在向(非常快速地)介绍以下内容后:
本页涵盖(更详细):
- Handlebars — 语法的必要基础知识
- 如何访问内容片段数据
- 使用嵌套内容片段
- 处理多值字段
- 创建循环和条件逻辑
- 内容片段的模板设计最佳实践
先决条件 prerequisites
要了解并使用此处介绍的技术,您应该拥有:
- 对HTML的基本了解
- 熟悉AEM内容片段和内容片段模型
- 了解您的内容片段模型
使用内容片段HTML模板 using-a-content-fragment-html-template
在AEM中使用内容片段HTML模板 using-a-content-fragment-html-template-in-aem
有关如何在AEM中使用模板的详细信息,请参阅:
使用可视化内容片段发布URL using-the-visual-content-fragment-publish-url
使用该模板创建可视内容片段后,您可以使用可视内容片段的发布URL。
Handlebars - (非常)基础知识 handlebars-the-very-basics
Handlebars是一种简单的模板语言,它使用双大括号(括号) {{ }}将动态内容插入到HTML中。
基本语法 basic-syntax
基本Handlebars语法的示例:
<!-- Output a variable (HTML-escaped) -->
{{snippet-not-found:variableName}}
<!-- Output raw HTML (unescaped) -->
{{{htmlContent}}}
<!-- Comment (not rendered) -->
{{! This is a comment }}
重要概念 key-concepts
Handlebars的主要概念:
{{ }}
转义HTML特殊字符
元数据、标签、布尔值
{{{ }}}
输出原始HTML(未转义)
富文本和资产输出
{{! }}
仅Handlebars注释
模板文档
对字段值使用三大括号({{{ }}}),因为值是预渲染的HTML。
模板上下文引用 template-context-reference
呈现模板时,它会接收一个上下文对象,其中包含有关您的内容片段的所有数据。 这将涵盖:
-
您选择的片段
-
从该选定片段引用的所有后续片段
| note |
| NOTE |
| 可以引用片段: |
- 在UI中:最大深度为5
- 使用API时:深度可配置,最大深度为10
|
内容片段 content-fragment
(所选)内容片段的上下文对象的结构:
allFields
列表
迭代的{name, value}数组
hasFields
布尔值
如果片段包含字段,则为true
属性结构 properties-structure
properties对象对于选定片段和每个引用的片段具有相同的结构。
title
字符串
片段的标题
骑自行车去犹他州南部
description
字符串
片段的描述
一次冒险……
path
字符串
片段的JCR路径
/content/dam/...
hasDescription
布尔值
如果描述不为空,则为真
true
createdDate
字符串
ISO-8601创建日期
modifiedDate
字符串
ISO-8601修改日期
publishedDate
字符串
ISO-8601发布日期
status
字符串
发布层的复制状态
DRAFT
model
地图
包含: id、path、name、technicalName、description
validationStatus
列表
{property, message}等条目
previewReplicationStatus
字符串
预览层的复制状态
tags
列表
片段级别标记。 每个项目: id、title、titlePath、name、path、description
fieldTags
列表
字段级标记。 与tags的结构相同。
示例:模板访问
对于(选定的)内容片段:
{{properties.title}}, {{properties.description}}, {{{fields.field_name}}}
引用的内容片段 referenced-content-fragments
任何引用片段的上下文对象的结构:
hasReferencedFragments
布尔值
存在引用时为true
referencedFragments
列表
引用的片段对象数组
referencesError
布尔值
加载引用时出现错误时的true
referencesErrorMessage
字符串
referencesError为true时的错误消息
引用的片段结构 referenced-fragment-structure
referencedFragments中的每个项目都包含:
anchorId
字符串
HTML安全锚点ID(在片段级别;不是内容片段属性)
properties
地图
片段元数据(与上述结构相同)
hasFields
布尔值
如果片段包含字段,则为真
allFields
列表
迭代的{name, value}数组
示例:第一个引用的内容片段(0索引列表中的第一个项目)的模板访问权限:
{{referencedFragments.[0].anchorId}}, {{referencedFragments.[0].properties.title}}, {{referencedFragments.[0].properties.description}}
或者,从字段映射中:
{{{ fields.referenced_cf_field_name.properties.description }}}
基本字段访问 basic-field-access
建议直接访问字段,如有必要,您可以循环访问所有字段。
直接字段访问(推荐) direct-field-access-recommended
使用字段映射直接按名称访问字段:
<!DOCTYPE html>
<html>
<head>
<title>{{properties.title}}</title>
</head>
<body>
<article>
<h1>{{{fields.title}}}</h1>
<p class="subtitle">{{{fields.subtitle}}}</p>
<div class="content">
{{{fields.description}}}
</div>
<div class="image">
{{{fields.primaryImage}}}
</div>
</article>
</body>
</html>
请记住:
- 如果字段值包含预呈现的HTML(富文本),请使用三大括号
{{{ }}}
- 字段名称(标题、子标题、描述、主图像)必须与您的内容片段模型完全匹配
- 未呈现缺少的字段 — 不引发任何错误,并且在呈现的HTML片段中,Handlebars语法仍然存在(并且可见)
循环访问所有字段 iterate-through-all-fields
如果您事先不知道字段名称,请使用allFields:
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Field Value</th>
</tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td>{{name}}</td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
请记住:
{{name}}使用双大括号(纯文本标签)
{{{value}}}使用三大括号(预渲染的HTML值)
嵌套内容片段 nested-content-fragments
当内容片段字段引用另一个内容片段时,您可以使用点表示法直接访问引用的片段中的字段。
单层嵌套 single-level-nesting
单级嵌套示例:
<article>
<h1>{{{fields.title}}}</h1>
<!-- Access author (a referenced Content Fragment) -->
<div class="author-info">
<h3>Author</h3>
<p>Name: {{{fields.author.name}}}</p>
<p>Email: {{{fields.author.email}}}</p>
<p>Bio: {{{fields.author.bio}}}</p>
</div>
<div class="content">
{{{fields.content}}}
</div>
</article>
模式: fields.referenceFieldName.nestedFieldName
多级嵌套 multi-level-nesting
系统支持无限的嵌套深度:
<article>
<h1>{{{fields.title}}}</h1>
<div class="author-details">
<!-- Level 1: Author -->
<p>Author: {{{fields.author.name}}}</p>
<!-- Level 2: Author's Organization -->
<p>Organization: {{{fields.author.organization.name}}}</p>
<p>Website: {{{fields.author.organization.website}}}</p>
<!-- Level 3: Organization's Address -->
<p>Located in: {{{fields.author.organization.address.city}}},
{{{fields.author.organization.address.country}}}</p>
</div>
<div class="content">
{{{fields.content}}}
</div>
</article>
模式: fields.level1.level2.level3.fieldName (有限的深度;默认值为5,使用API时可以扩展到10)
API参数要求:水化 api-parameter-requirements
要启用嵌套内容片段访问,必须在API调用中包含hydration查询参数:
要启用水化,请执行以下操作:
# Enable hydration with depth=2 for 2 levels of nesting
GET /adobe/sites/cf/fragments/{id}/preview?hydration=%7B%22enabled%22%3Atrue%2C%22maxDepth%22%3A2%7D
多值字段 multi-valued-fields
多值字段有多种类型。
多值文本字段 multi-valued-text-fields
多值时文本、数字、日期和其他简单字段变为数组:
<article>
<h1>{{{fields.title}}}</h1>
<!-- Access individual items by index (use dot before bracket) -->
<div class="tags">
<span class="tag">{{{fields.tags.[0]}}}</span>
<span class="tag">{{{fields.tags.[1]}}}</span>
</div>
<!-- Better: Iterate through all tags -->
<div class="tags">
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
</div>
</article>
请记住,在Handlebars中按索引访问数组项时:
多值数字字段 multi-valued-number-fields
数字将转换为字符串以进行渲染:
<div class="pricing">
<h3>Available Prices:</h3>
{{#each fields.prices}}
<span class="price">${{{this}}}</span>
{{/each}}
</div>
多值内容片段引用 multi-valued-content-fragment-references
当字段引用多个内容片段时:
<div class="authors">
<h3>Authors:</h3>
{{#each fields.authors}}
<div class="author">
<h4>{{{this.name}}}</h4>
<p>Email: {{{this.email}}}</p>
{{#if this.bio}}
<p class="bio">{{{this.bio}}}</p>
{{/if}}
</div>
{{/each}}
</div>
多值资产引用 multi-valued-asset-references
为作为资源的内容类型(例如,图像和文档)配置的内容引用字段将预呈现为HTML。 多值资产变为数组:
<!-- Single asset -->
<div class="hero-image">
{{{fields.heroImage}}}
</div>
<!-- Multi-valued: iterate through all images -->
<div class="gallery">
{{#each fields.gallery}}
<div class="image">{{{this}}}</div>
{{/each}}
</div>
嵌套的多值引用 nested-multi-valued-references
多值引用可以包含任何深度的多值引用:
{{#each fields.chapters}}
<div class="chapter">
<h3>Chapter: {{{this.title}}}</h3>
{{#each this.authors}}
<p>Author: {{{this.name}}}</p>
{{#each this.publications}}
<p>Publication: {{{this.title}}}</p>
{{/each}}
{{/each}}
</div>
{{/each}}
循环和迭代 loops-and-iteration
Handlebars提供了用于迭代数组与对象的{{#each}}帮助程序。
对阵列进行迭代 iterating-over-arrays
循环访问数组的示例:
<!-- Simple array iteration -->
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
<!-- Array of objects -->
{{#each fields.authors}}
<div class="author">
<h4>{{{this.name}}}</h4>
<p>{{{this.email}}}</p>
</div>
{{/each}}
<!-- With empty-state fallback -->
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{snippet-not-found:else}}
<p>No tags available.</p>
{{/each}}
循环中的特殊变量 special-variables-in-loops
在{{#each}}块内,Handlebars提供特殊变量:
{{#each fields.items}}
<div class="item">
<p>Index: {{@index}}</p> <!-- 0-based index -->
<p>Number: {{@number}}</p> <!-- 1-based index -->
<p>First: {{@first}}</p> <!-- true for first item -->
<p>Last: {{@last}}</p> <!-- true for last item -->
<p>Value: {{{this}}}</p> <!-- current item -->
</div>
{{/each}}
<!-- Example: numbered steps with first/last CSS classes -->
<ul>
{{#each fields.steps}}
<li class="{{#if @first}}first{{/if}} {{#if @last}}last{{/if}}">
Step {{@number}}: {{{this}}}
</li>
{{/each}}
</ul>
迭代引用的片段 iterating-over-referenced-fragments
迭代引用的片段的示例:
{{#if hasReferencedFragments}}
<section class="references">
<h2>Related Content</h2>
{{#each referencedFragments}}
<article id="{{anchorId}}">
<h3>{{title}}</h3>
{{#if hasDescription}}
<p>{{description}}</p>
{{/if}}
{{#if hasFields}}
<ul>
{{#each allFields}}
<li><strong>{{name}}:</strong> {{{value}}}</li>
{{/each}}
</ul>
{{/if}}
</article>
{{/each}}
</section>
{{/if}}
嵌套循环 nested-loops
嵌套循环的示例:
{{#each fields.categories}}
<section class="category">
<h2>{{{this.name}}}</h2>
{{#each this.products}}
<article class="product">
<h3>{{{this.name}}}</h3>
<p>{{{this.description}}}</p>
</article>
{{/each}}
</section>
{{/each}}
条件渲染 conditional-rendering
使用条件根据数据可用性显示或隐藏内容。
基本If/Else basic-if-else
基本if-else构造的示例:
{{#if hasMainDescription}}
<p class="description">{{properties.description}}</p>
{{snippet-not-found:else}}
<p class="no-description">No description available.</p>
{{/if}}
<!-- Check field existence before rendering -->
{{#if fields.author}}
<div class="author">
<p>By {{{fields.author.name}}}</p>
</div>
{{/if}}
{{#if fields.publishDate}}
<time>{{{fields.publishDate}}}</time>
{{/if}}
Unless(负条件) unless-negative-conditional
unless辅助函数:
<!-- Show author unless explicitly hidden -->
{{#unless fields.hideAuthor}}
<div class="author">{{{fields.author.name}}}</div>
{{/unless}}
嵌套条件 nested-conditials
嵌套条件示例:
{{#if fields.author}}
<div class="author">
<h3>{{{fields.author.name}}}</h3>
{{#if fields.author.bio}}
<p class="bio">{{{fields.author.bio}}}</p>
{{/if}}
{{#if fields.author.website}}
<a href="{{{fields.author.website}}}">Visit Website</a>
{{/if}}
</div>
{{/if}}
内置Handlebars帮助程序 built-in-handlebars-helpers
Handlebars包含多个内置帮助程序,超出{{#if}}和{{#each}}。
{{#if condition}}
如果条件为真,则呈现内容。 假值: false、undefined、null、0、""、[]
{{#unless condition}}
如果条件为假(与#if相反),则呈现内容
{{#each array}}
为每个项目重复内容;对于空数组支持{{else}}
{{#with object}}
为嵌套对象创建新的范围,减少路径重复
{{lookup this "key"}}
按名称动态查找属性
使用辅助函数 with-helper
为嵌套对象创建新的范围,以减少重复的路径前缀:
{{#with fields.author}}
<div class="author">
<h3>{{{name}}}</h3> <!-- same as fields.author.name -->
<p>{{{email}}}</p> <!-- same as fields.author.email -->
<p>{{{bio}}}</p> <!-- same as fields.author.bio -->
</div>
{{/with}}
<!-- Useful for deeply nested objects -->
{{#with fields.author.organization}}
<div class="organization">
<h4>{{{name}}}</h4>
<p>{{{website}}}</p>
{{#with address}}
<address>
{{{street}}}<br/>
{{{city}}}, {{{country}}}
</address>
{{/with}}
</div>
{{/with}}
前进模式 advanced-patterns
下面是高级模式的一些示例。
访问嵌套循环中的父上下文 accessing-parent-context-in-nested-loops
使用../从嵌套循环内访问父作用域:
<h1>{{{fields.title}}}</h1>
{{#each fields.chapters}}
<section class="chapter">
<h2>Chapter {{@number}}: {{{this.title}}}</h2>
{{#each this.sections}}
<article>
<!-- Access parent chapter via ../ -->
<p>Chapter: {{{../title}}}</p>
<!-- Access root context via ../../ -->
<p>Book: {{{../../fields.title}}}</p>
<h3>{{{this.title}}}</h3>
<div>{{{this.content}}}</div>
</article>
{{/each}}
</section>
{{/each}}
动态CSS类 dynamic-css-classes
动态CSS类的示例:
<article class="content-fragment {{#if hasMainDescription}}with-description{{/if}} {{#if hasReferencedFragments}}has-refs{{/if}}">
<h1>{{properties.title}}</h1>
</article>
<ul class="tag-list">
{{#each fields.tags}}
<li class="tag {{#if @first}}first{{/if}} {{#if @last}}last{{/if}}">
{{{this}}}
</li>
{{/each}}
</ul>
完整示例 complete-examples
提供了几个完整的示例以供参考。
有作者的博客帖子
包含作者详细信息的博客帖子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{properties.title}}</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.author-card { background: #f5f5f5; padding: 20px; border-radius: 8px; }
.tags { display: flex; gap: 10px; }
.tag { background: #007bff; color: white; padding: 5px 10px; border-radius: 4px; }
</style>
</head>
<body>
<article>
<header>
<h1>{{{fields.title}}}</h1>
{{#if fields.publishDate}}
<time datetime="{{{fields.publishDate}}}">{{{fields.publishDate}}}</time>
{{/if}}
{{#if fields.tags}}
<div class="tags">
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
</div>
{{/if}}
</header>
{{#if fields.heroImage}}
<figure>
{{{fields.heroImage}}}
{{#if fields.imageCaption}}
<figcaption>{{{fields.imageCaption}}}</figcaption>
{{/if}}
</figure>
{{/if}}
<div class="content">
{{{fields.content}}}
</div>
{{#if fields.author}}
<aside class="author-card">
<h3>About the Author</h3>
<h4>{{{fields.author.name}}}</h4>
{{#if fields.author.profilePicture}}
<div class="author-image">{{{fields.author.profilePicture}}}</div>
{{/if}}
{{#if fields.author.bio}}
<p>{{{fields.author.bio}}}</p>
{{/if}}
{{#if fields.author.email}}
<p>Contact: <a href="mailto:{{{fields.author.email}}}">{{{fields.author.email}}}</a></p>
{{/if}}
</aside>
{{/if}}
</article>
</body>
</html>
所需的API调用:
GET /adobe/sites/cf/fragments/{id}/preview?hydration=%7B%22enabled%22%3Atrue%2C%22maxDepth%22%3A1%7D
通用表视图(事先不了解字段) generic-table-view-no-prior-knowledge-of-fields
一种通用的表格视图,它不具备字段的内在知识。 与 通用模板 类似:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{properties.title}}</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
th { background-color: #f4f4f4; font-weight: bold; }
.ref-section { background: #f9f9f9; padding: 20px; margin: 20px 0; border-radius: 8px; }
</style>
</head>
<body>
<header>
<h1>{{properties.title}}</h1>
{{#if properties.description}}<p>{{properties.description}}</p>{{/if}}
<p><small>Path: {{properties.path}}</small></p>
</header>
{{#if hasFields}}
<section>
<h2>Fields</h2>
<table>
<thead>
<tr><th>Field Name</th><th>Field Value</th></tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td><strong>{{name}}</strong></td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
{{/if}}
{{#if hasReferencedFragments}}
<section class="ref-section">
<h2>Referenced Content Fragments</h2>
{{#each referencedFragments}}
<article id="{{anchorId}}" style="margin-bottom: 30px;">
<h3>{{title}}</h3>
{{#if hasDescription}}<p>{{description}}</p>{{/if}}
<p><small>Path: {{path}}</small></p>
{{#if hasFields}}
<table>
<thead>
<tr><th>Field Name</th><th>Field Value</th></tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td><strong>{{name}}</strong></td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{/if}}
</article>
{{/each}}
</section>
{{/if}}
</body>
</html>
最佳实践 best-practices
最佳实践包括:
-
对于包含HTML标记内容的字段值,始终使用三大括号。
-
字段值在HTML中预呈现。
| note |
| NOTE |
| 双大括号将原始HTML标签显示为纯文本。 |
| code language-handlebars |
<!-- CORRECT -->
{{{fields.description}}}
<!-- WRONG - displays HTML tags as text -->
{{fields.description}}
|
-
在访问嵌套字段之前检查是否存在。
| code language-handlebars |
<!-- GOOD: check before accessing nested fields -->
{{#if fields.author}}
<p>By {{{fields.author.name}}}</p>
{{/if}}
<!-- RISKY: may render empty if author is not set -->
<p>By {{{fields.author.name}}}</p>
|
-
尽可能使用直接字段访问。
- 它比迭代
allFields并按名称匹配更易读取和维护。
-
带部分注释的结构模板。
| code language-handlebars |
{{! ===== HEADER SECTION ===== }}
<header>
<h1>{{properties.title}}</h1>
</header>
{{! ===== MAIN CONTENT ===== }}
<main>
{{#if hasFields}}
<!-- fields rendering -->
{{/if}}
</main>
{{! ===== REFERENCES ===== }}
{{#if hasReferencedFragments}}
<!-- references rendering -->
{{/if}}
|
-
使用回退轻松处理缺失数据。
| code language-handlebars |
{{#if fields.title}}
<h1>{{{fields.title}}}</h1>
{{snippet-not-found:else}}
<h1>Untitled</h1>
{{/if}}
|
-
始终使用正确的HTML文档结构。
| code language-handlebars |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{properties.title}}</title>
</head>
<body>
<!-- your content here -->
</body>
</html>
|
-
通过多种内容方案进行测试:
- 所有字段已完全填充
- 可选字段缺失
- 清空多值字段
- 深度嵌套(多级)
- 无法加载的引用
-
使用语义HTML元素:
- 为了获得更好的辅助功能,请使用
<article>、<header>、<main>、<footer>、<time>、<address>或类似项。
-
将样式保留在CSS中。
- 使用
<style>标记或外部样式表。
- 尽可能避免使用内联样式。
-
记录复杂逻辑:
- 使用Handlebars注释
({{! }})。
- 请勿使用HTML注释,这些注释会显示在渲染的输出中。
疑难解答 troubleshooting
一些故障排除提示包括:
字段以文本形式显示HTML标记
<p>Hello World</p>按字面显示
使用三大括号: {{{fields.description}}}
嵌套的内容片段字段为空或显示[对象Object]
{{{fields.author.name}}}为空
在API调用中启用水合;验证字段名称拼写;检查maxDepth是否足够深
多值字段仅显示第一项
具有五个项目的数组仅呈现一个
使用{{#each fields.tags}}迭代所有项
数组索引访问不起作用
{{{fields.tags[0]}}}呈现为空
使用点括号语法: {{{fields.tags.[0]}}}
引用的片段未出现
hasReferencedFragments始终为false
启用水合: ?hydration=%7B%22enabled%22%3Atrue%7D;还检查{{#if referencesError}}
模板不呈现任何内容
空页面或空输出
检查未关闭的{{#if}}或{{#each}}块;添加诊断输出: <pre>hasFields: {{hasFields}} | title: {{properties.title}}</pre>
评论会显示在渲染的页面中
对最终用户可见的HTML注释文本
使用Handlebars注释{{! comment }}而不是HTML <!-- comment -->
条件属性的计算结果始终为true
{{#if fields.enabled}}始终为真
注意:字符串"false"在Handlebars中为truthy。 只有实际的false、null、undefined、0、""和[]是假的。
特殊字符作为实体呈现
显示<,&而不是<,&
对预渲染的HTML内容使用三大括号: {{{fields.content}}}
无法从内环访问外环变量
来自父级#each的变量未定义
将../用于父作用域: {{{../name}}};将../../用于祖父
空列表未显示回退消息
零项的多值字段不显示任何内容
在{{#each}}中使用{{else}}: {{#each fields.tags}}...{{else}}<p>No tags</p>{{/each}}
使用资产 working-with-assets
从内容片段引用的Assets将由AEM预呈现为HTML。 因此,所有资产参考都必须使用三大括号。
图像
<img src="..." alt="...">
请记住:
- 资产字段始终使用三大括号。
使用双大括号将转义生成的HTML标记,并将其显示为原始文本,而不是呈现图像、视频或链接。
资源字段使用情况 asset-field-usage
资源字段用法示例:
<!-- CORRECT - triple braces render the image -->
{{{fields.heroImage}}}
<!-- Output: <img src="path/to/image.jpg" alt="Hero"> -->
<!-- WRONG - double braces escape the tag, showing it as text -->
{{fields.heroImage}}
<!-- Output: <img src="path/to/image.jpg" alt="Hero"> -->
自定义模板帮助程序 customer-template-helpers
系统提供自定义Handlebars帮助程序,用于生成具有自定义HTML属性的HTML元素。 这些帮助程序让您能够控制生成的标记,同时处理从预呈现内容中提取源URL的复杂性。
可用的帮助程序:
asset — 生成具有自定义属性的<img>标记
text — 生成<span>标记,这些标记将文本内容与自定义属性环绕
asset帮助程序 asset-helper
语法:
{{{asset fieldValue attribute1="value1" attribute2="value2"}}}
请记住:
- 资产帮助程序使用三大括号
{{{ }}},而不是双大括号!
四个基本示例 four-basic-examples
四个基本示例包括:
<!-- Add a CSS class to an image -->
{{{asset fields.heroImage class="hero-image"}}}
<!-- Output: <img src="..." alt="..." class="hero-image"> -->
<!-- Add multiple CSS classes -->
{{{asset fields.productImage class="product-img responsive shadow"}}}
<!-- Add id and class -->
{{{asset fields.logo class="brand-logo" id="main-logo"}}}
<!-- Add data attributes -->
{{{asset fields.thumbnail class="thumb" data-category="product" data-id="123"}}}
支持的属性 supported-attributes
您可以添加任何有效的HTML属性:
class
class="my-class another-class"
alt
alt="Custom alt text" (overrides existing alt)
data-*
data-index="1" data-type="hero"
aria-*
aria-label="Description" aria-hidden="true"
style
style="border-radius: 8px;"
覆盖替换文本 override-alt-text
可以覆盖原始图像中的alt属性:
{{{asset fields.photo alt="Custom description for accessibility"}}}
复杂示例 complex-example
一个复杂的示例是:
<article class="blog-post">
<header>
{{{asset fields.featuredImage
class="featured-image responsive"
id="post-hero"
loading="lazy"
data-post-id="12345"}}}
</header>
</article>
与循环一起使用 using-with-loops
循环中的资产帮助程序:
{{#each fields.galleryImages}}
{{{asset this class="gallery-item" data-index=@index}}}
{{/each}}
text帮助程序 text-helper
文本帮助程序生成一个包含自定义CSS类和HTML属性的文本内容换行的<span>标记。 用于设置单个文本字段的样式。
语法:
{{{text fieldValue attribute1="value1" attribute2="value2"}}}
请记住:
- 文本辅助函数使用三大括号
{{{ }}},而不是双大括号!
三个基本示例 three-basic-examples
三个基本示例包括:
<!-- Add a CSS class to text -->
{{{text fields.title class="article-title"}}}
<!-- Output: <span class="article-title">The Title Text</span> -->
<!-- Add multiple attributes -->
{{{text fields.price class="price-tag" id="product-price" data-currency="USD"}}}
<!-- Style inline text -->
{{{text fields.highlightedText class="highlighted" style="background: yellow;"}}}
常见用例 common-use-cases
一些常见用例包括:
<!-- Styling article metadata -->
<article>
<header>
{{{text fields.category class="category-badge"}}}
<h1>{{{fields.title}}}</h1>
{{{text fields.author class="byline"}}}
{{{text fields.publishDate class="date"}}}
</header>
</article>
<!-- Creating styled labels -->
<div class="product-card">
{{{text fields.productName class="product-name"}}}
{{{text fields.brand class="brand-label" data-brand-id="abc"}}}
{{{text fields.price class="price" id="main-price"}}}
</div>
<!-- Accessibility enhancements -->
{{{text fields.importantNote class="alert" role="alert" aria-live="polite"}}}
带循环 with-loops
循环的常见用例包括:
{{#each fields.tags}}
{{{text this class="tag-badge"}}}
{{/each}}
帮助程序 — 属性验证 helpers-attribute-validation
两个帮助程序都会先验证属性名称,然后再将其包含在输出中。
有效的属性名称:
将以静默方式跳过无效的属性名称,日志中会显示警告:
{{{asset fields.image class="valid" 123-invalid="skipped" id="also-valid"}}}
<!-- Output: <img src="..." alt="..." class="valid" id="also-valid"> -->
<!-- 123-invalid is skipped because it starts with a number -->
请记住:
- 检查服务器日志中是否存在“阻止的无效属性名称格式”警告。
比较直接输出与帮助程序 comparing-direct-output-to-helpers
何时添加直接输出{{{fields.xxx}}}:
- 您不需要自定义样式
- 您希望默认输出保持不变
- 该字段包含您不想修改的复杂HTML
何时使用辅助函数:
- 您需要添加用于样式设置的CSS类
- 您需要添加自定义HTML属性(
data-*、aria-*等)
- 您需要一致的、受控制的HTML结构
比较:
<!-- Direct output - uses whatever HTML the system generates -->
{{{fields.heroImage}}}
<!-- Output: <img src="/path/image.jpg" alt="Hero Image"> -->
<!-- With asset helper - full control over attributes -->
{{{asset fields.heroImage class="hero responsive" id="main-hero" loading="lazy"}}}
<!-- Output: <img src="/path/image.jpg" alt="Hero Image" class="hero responsive" id="main-hero" loading="lazy"> -->
快速参考 quick-reference
提供了一些快速参考信息以供参考。
上下文变量 context-variables
上下文变量:
{{properties}} <!-- Main fragment metadata -->
{{fields}} <!-- Map keyed by field name to rendered values (such as strings, lists, nested maps for Content Fragment references, commerce maps, HTML, and others) -->
{{allFields}} <!-- List of { name, value } maps (uniform iteration) -->
{{hasFields}}. <!-- Boolean -->
{{hasReferencedFragments}}. <!-- Boolean -->
{{referencedFragments}} <!-- List of referenced-fragment maps -->
字段访问 field-access
如何访问字段:
{{{fields.fieldName}}} <!-- Direct field -->
{{{fields.author.name}}} <!-- Nested Content Fragment field -->
{{{fields.author.org.address.city}}} <!-- Multi-level nesting -->
{{{fields.tags.[0]}}} <!-- Array by index -->
{{#each fields.tags}}...{{/each}} <!-- Array iteration -->
{{{fields.authors.[0].name}}} <!-- Multi-valued Content Fragment reference -->
控制流 control-flow
控制流:
{{#if condition}}...{{/if}} <!-- Conditional -->
{{#if condition}}...{{else}}...{{/if}} <!-- If/else -->
{{#unless condition}}...{{/unless}} <!-- Negative conditional -->
{{#each array}}...{{/each}} <!-- Iteration -->
{{#each array}}...{{else}}...{{/each}} <!-- Iteration with fallback -->
{{#with object}}...{{/with}} <!-- Change scope -->
循环变量 loop-variables
循环变量:
{{@index}} <!-- 0-based index -->
{{@number}} <!-- 1-based index -->
{{@first}} <!-- true for first item -->
{{@last}} <!-- true for last item -->
{{@key}} <!-- Object property name -->
{{this}} <!-- Current item -->
{{../parent}} <!-- Access parent scope -->
自定义模板帮助程序 custom-template-helpers
自定义模板帮助程序:
{{{asset fields.image class="css-class"}}} <!-- Image with class -->
{{{asset fields.image class="c1" id="my-id"}}} <!-- Image with multiple attrs -->
{{{asset fields.image alt="Custom alt text"}}} <!-- Override alt text -->
{{{asset fields.image loading="lazy" data-x="val"}}} <!-- Custom attributes -->
{{{text fields.title class="title-class"}}} <!-- Span with class -->
{{{text fields.price class="price" id="p1"}}} <!-- Span with multiple attrs -->
{{{text this class="item" data-index=@index}}} <!-- In loops -->
其他资源 additional-resources
其他资源可供使用:
experience-manager-cloud-service-help-main-toc