17

目标是定义一种 HTML 结构,该结构具有多个由调用者声明的内容块。例如,标题、正文和内容。生成的标记应为:

<header>My header</header>
<div class="body">My body</div>
<footer>My footer</footer>

实例化组件的模板将定义三个部分中的每一个My headerMy body、 和My footer

使用 Ruby on Rails,您可以content_for :header从调用者那里捕获标头内容,并yield :header对其进行插值。

这在 ember.js 中可行吗?

4

2 回答 2

19

从 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}}
于 2015-05-17T01:20:13.923 回答
6

之前的回复可能已过时。

这个问题有一个公认的 RFC;命名模板块 API将支持将多个块传递给组件。

从 Ember 2.3 开始,上下文组件允许另一种处理这种情况的方法:

将您的组件拆分为多个子组件,并将子组件作为块参数传递回组件;此设置允许设置每个子组件块的内容。

查看Twiddle 的完整示例

// 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}}

此解决方案不强制组件 API/结构,如果子组件被省略、多次添加或顺序错误,则组件可能会被错误使用,在这些情况下,组件将生成不需要的内容。

查看Twiddle 的完整示例

于 2018-09-20T12:22:56.270 回答