Spacebars 模板
Spacebars 是一种类似于 Handlebars 的模板语言,它基于渲染反应式变化的数据上下文的概念。Spacebars 模板看起来像简单的 HTML,带有特殊的“mustache”标签,由花括号分隔:{{ }}
。
例如,考虑 Todos 示例应用程序中的Todos_item
模板
1 | <template name="Todos_item"> |
此模板期望使用具有键todo
的对象作为数据上下文进行渲染(我们将在下面看到如何强制执行此操作)。我们使用 mustache 标签访问todo
的属性,例如{{todo.text}}
。默认行为是将该属性渲染为字符串;但是,对于某些属性(例如checked={{todo.checked}}
),它可以解析为布尔值。
请注意,像这样的简单字符串插值将始终为您转义任何 HTML,因此您不需要执行 XSS 的安全检查。
此外,我们可以看到模板助手的示例——{{checkedClass todo}}
调用在单独的 JavaScript 文件中定义的checkedClass
助手。HTML 模板和 JavaScript 文件一起定义了Todos_item
组件
1 | Template.Todos_item.helpers({ |
在 Blaze 助手上下文中,this
的作用域是使用助手时的当前数据上下文。这可能难以理解,因此通常最好将所需数据作为参数传递给助手(就像我们在这里做的那样)。
除了简单插值之外,mustache 标签还可用于模板中的控制流。例如,在Lists_show
模板中,我们这样渲染 todos 列表
1 | {{#each todo in todos}} |
此代码段说明了几件事
{{#each .. in}}
块助手,它为数组或游标中的每个元素重复一个 HTML 块,或者在没有项目存在时渲染{{else}}
块的内容。- 模板包含标签
{{> Todos_item (todoArgs todo)}}
,它使用todosArg
助手返回的数据上下文渲染Todos_item
组件。
您可以在Spacebars 文档中阅读有关完整语法的详细信息。在本节中,我们将尝试介绍一些超出语法本身的重要细节。
数据上下文和查找
我们已经看到{{todo.title}}
访问当前数据上下文上todo
项的title
属性。此外,..
访问父数据上下文(很少是一个好主意),list.todos.[0]
访问list
上todos
数组的第一个元素。
请注意,Spacebars 对null
值非常宽容。如果您尝试访问null
值的属性(例如,如果foo
未定义,则为foo.bar
),它不会抱怨,而是将其简单地视为 null。但是,对此有一些例外——尝试调用null
函数,或在助手内部执行相同的操作将导致异常。
使用参数调用助手
您可以像checkedClass
一样为助手提供参数,只需将参数放在助手调用之后,例如:{{checkedClass todo true 'checked'}}
。您还可以使用{{checkedClass todo noClass=true classname='checked'}}
为助手提供命名关键字参数列表。当您传递关键字参数时,您需要从最终参数的hash
属性中读取它们。以下是我们刚才看到的示例
1 | Template.Todos_item.helpers({ |
请注意,使用关键字参数传递助手有点笨拙,因此通常最好避免它们。此功能包含在内是为了历史原因,以匹配关键字参数在 Handlebars 中的工作方式。
您还可以将助手的输出传递给模板包含或其他助手。为此,请使用括号来显示优先级
1 | {{> Todos_item (todoArgs todo)}} |
这里将todo
作为参数传递给todoArgs
助手,然后将输出传递到Todos_item
模板中。
模板包含
您使用{{> }}
语法“包含”一个子组件。默认情况下,子组件将获得调用者的数据上下文,但通常最好明确说明。您可以提供一个将成为整个数据上下文的单个对象(就像我们在上面使用todoArgs
助手返回的对象一样),或者提供一个关键字参数列表,这些参数将被组合成一个对象,如下所示
1 | {{> subComponent arg1="value-of-arg1" arg2=helperThatReturnsValueOfArg2}} |
在这种情况下,subComponent
组件可以预期以下形式的数据上下文
1 | { |
属性助手
我们在上面看到,使用形式为checked={{todo.checked}}
的助手(或数据上下文查找)将在todo.checked
评估为 true 时将 checked 属性添加到 HTML 标签。此外,您还可以直接将对象包含在 HTML 元素的属性列表中以一次设置多个属性
1 | <a {{attributes}}>My Link</a> |
1 | Template.foo.helpers({ |
渲染原始 HTML
虽然默认情况下 mustache 标签会转义 HTML 标签以避免XSS,但您可以使用三连字符渲染原始 HTML:{{{ }}}
。
1 | {{{myHtml}}} |
1 | Template.foo.helpers({ |
您应该非常小心地执行此操作,并始终确保您没有从这样的助手返回用户生成的内容(或者如果您这样做,请转义它!)。
块助手
块助手,使用{{# }}
调用,是一个助手,它接受(并可能渲染)一个 HTML 块。例如,我们在上面看到了{{#each .. in}}
助手,它对列表中的每个项目重复给定的 HTML 块。您还可以使用模板作为块助手,通过Template.contentBlock
和Template.elseBlock
渲染其内容。例如,您可以使用以下方法创建自己的{{#if}}
助手
1 | <template name="myIf"> |
内置块助手
有一些内置的块助手值得了解
如果 / 除非
{{#if}}
和{{#unless}}
助手非常简单直观,但对于控制模板的控制流至关重要。两者都通过评估其单个参数并检查其真值来工作。在 JS 中,null
、undefined
、0
、''
、NaN
和false
被认为是“假值”,所有其他值都被认为是“真值”。
1 | {{#if something}} |
每个-在
{{#each .. in}}
助手是在保留外部数据上下文的情况下遍历列表的便捷方式。
1 | {{#each todo in todos}} |
让
{{#let}}
助手有助于在模板中捕获助手的输出或文档子属性。将其视为使用 JavaScript let
定义变量一样。
1 | {{#let name=person.bio.firstName color=generateColor}} |
请注意,name
和color
(以及上面的todo
)仅在模板作用域中添加;它们不会添加到数据上下文中。具体来说,这意味着在助手和事件处理程序中,您无法使用this.name
或this.color
访问它们。如果您需要在助手内部访问它们,则应将它们作为参数传递(就像我们在上面的(todoArgs todo)
中所做的那样)。
每个和与
还有两个 Spacebars 内置助手{{#each}}
和{{#with}}
,我们不建议使用它们(请参阅建议使用 each-in)。这些块助手会在模板中更改数据上下文,这可能难以理解。
与{{#each .. in}}
类似,{{#each}}
会遍历数组或游标,将内容块中的数据上下文更改为当前迭代中的项目。{{#with}}
只是将自身内部的数据上下文更改为提供的对象。在大多数情况下,最好使用{{#each .. in}}
和{{#let}}
,就像使用变量声明比使用 JavaScript with
关键字更好一样。
块助手的链接
您可以链接块助手
1 | {{#input isRadio}} |
这等效于
1 | {{#input isRadio}} |
严格性
Spacebars 具有非常严格的 HTML 解析器。例如,您不能在 Spacebars 中自闭合div
(<div/>
),并且您需要关闭浏览器可能不需要关闭的某些标签(例如<p>
标签)。值得庆幸的是,解析器会在无法理解您的代码时用错误的确切行号发出警告。
转义
要插入文字花括号:{{ }}
等,请在起始花括号中添加一个管道字符|
1 | <!-- will render as <h1>All about {{</h1> --> |