如何将多个内容生成 ember.js 组件模板?
How can I yield multiple pieces of content into an ember.js component template?
目标是定义一个 HTML 的结构,其中包含调用方声明的多个内容块。例如,header、body和内容。生成的标记应为:
<header>My header</header>
<div class="body">My body</div>
<footer>My footer</footer>
实例化组件的模板将定义三个部分中的每一个,My header
、My body
和 My footer
。
在 Rails 上使用 Ruby,您将使用 content_for :header
从调用方捕获 header 内容,并使用 yield :header
对其进行插值。
这在 ember.js 中可行吗?
从 ember v1.10 开始,yield 接受参数。然而 handlebars 还不允许对变量值进行内联比较。通过在组件上定义一些属性,我们可以非常接近 rails 所做的事情。
根据上面的示例,组件的模板如下所示:
<header>{{yield header}}</header>
<div class="body">{{yield body}}</div>
<footer>{{yield footer}}</footer>
并且组件定义会将变量参数解析为 yield 语句:
export default Ember.Component.extend({
header: {isHeader: true},
footer: {isFooter: true},
body: {isBody: true}
});
这意味着 {{yield header}}
实际上正在向消费模板生成一个对象 {isHeader: true}
。所以我们可以使用嵌套的 if/else 结构来声明三个部分,如下所示:
{{#my-comp as |section|}}
{{#if section.isHeader}}
My header
{{else if section.isBody}}
My body
{{else if section.isFooter}}
My footer
{{/if}}
{{/my-comp}}
之前的回复可能已经过时了。
这个问题有一个公认的 RFC; Named Templates Block API 将支持将多个块传递给一个组件。
从 Ember 2.3 开始,Contextual components 允许另一种方法处理这种情况:
Split your component into multiple subcomponents and pass the subcomponents back to the component as block parameters; this setup allows to set the content of each subcomponent block.
// my-component.js
{{yield (hash
header = (component 'my-header')
content = (component 'my-content')
footer = (component 'my-footer')
)}}
{{#unless hasBlock}}
{{my-header}}
{{my-content}}
{{my-footer}}
{{/unless}}
// my-{header/content/footer}.js
{{#if hasBlock}}
{{yield}}
{{else}}
Default xxxxx
{{/if}}
在这种情况下,您可以使用默认组件内容或将特定内容传递给任何子组件,例如:
{{my-component}}
{{#my-component as |f|}}
{{f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{f.footer}}
{{/my-component}}
{{#my-component as |f|}}
{{#f.header}}
Custom header
{{/f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{#f.footer}}
Custom footer
{{/f.footer}}
{{/my-component}}
This solution does not force the component API/structure, then the component could be wrongly used if a subcomponent is omitted, added multiple times, or have the wrong order, in these cases the component will generate an undesired content.
目标是定义一个 HTML 的结构,其中包含调用方声明的多个内容块。例如,header、body和内容。生成的标记应为:
<header>My header</header>
<div class="body">My body</div>
<footer>My footer</footer>
实例化组件的模板将定义三个部分中的每一个,My header
、My body
和 My footer
。
在 Rails 上使用 Ruby,您将使用 content_for :header
从调用方捕获 header 内容,并使用 yield :header
对其进行插值。
这在 ember.js 中可行吗?
从 ember v1.10 开始,yield 接受参数。然而 handlebars 还不允许对变量值进行内联比较。通过在组件上定义一些属性,我们可以非常接近 rails 所做的事情。
根据上面的示例,组件的模板如下所示:
<header>{{yield header}}</header>
<div class="body">{{yield body}}</div>
<footer>{{yield footer}}</footer>
并且组件定义会将变量参数解析为 yield 语句:
export default Ember.Component.extend({
header: {isHeader: true},
footer: {isFooter: true},
body: {isBody: true}
});
这意味着 {{yield header}}
实际上正在向消费模板生成一个对象 {isHeader: true}
。所以我们可以使用嵌套的 if/else 结构来声明三个部分,如下所示:
{{#my-comp as |section|}}
{{#if section.isHeader}}
My header
{{else if section.isBody}}
My body
{{else if section.isFooter}}
My footer
{{/if}}
{{/my-comp}}
之前的回复可能已经过时了。
这个问题有一个公认的 RFC; Named Templates Block API 将支持将多个块传递给一个组件。
从 Ember 2.3 开始,Contextual components 允许另一种方法处理这种情况:
Split your component into multiple subcomponents and pass the subcomponents back to the component as block parameters; this setup allows to set the content of each subcomponent block.
// my-component.js
{{yield (hash
header = (component 'my-header')
content = (component 'my-content')
footer = (component 'my-footer')
)}}
{{#unless hasBlock}}
{{my-header}}
{{my-content}}
{{my-footer}}
{{/unless}}
// my-{header/content/footer}.js
{{#if hasBlock}}
{{yield}}
{{else}}
Default xxxxx
{{/if}}
在这种情况下,您可以使用默认组件内容或将特定内容传递给任何子组件,例如:
{{my-component}}
{{#my-component as |f|}}
{{f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{f.footer}}
{{/my-component}}
{{#my-component as |f|}}
{{#f.header}}
Custom header
{{/f.header}}
{{#f.content}}
Custom content
{{/f.content}}
{{#f.footer}}
Custom footer
{{/f.footer}}
{{/my-component}}
This solution does not force the component API/structure, then the component could be wrongly used if a subcomponent is omitted, added multiple times, or have the wrong order, in these cases the component will generate an undesired content.