Как я могу преобразовать несколько фрагментов контента в шаблон компонента ember.js?

Цель состоит в том, чтобы определить структуру HTML, которая имеет более одного блока содержимого, объявленного вызывающей стороной. Например, заголовок, тело и содержимое. В результате разметка должна быть:

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

Шаблон, реализующий компонент, будет определять каждый из трех разделов: My header, My body и My footer.

В Ruby on Rails вы должны использовать content_for :header для захвата содержимого заголовка от вызывающего объекта и yield :header для его интерполяции.

Возможно ли это в ember.js?


person aceofspades    schedule 17.05.2015    source источник


Ответы (2)


Начиная с ember v1.10, yield принимает параметры. Однако handlebars еще не позволяет выполнять встроенное сравнение значений переменных. Определив некоторые свойства компонента, мы можем приблизиться к тому, что делает рельс.

В приведенном выше примере шаблон компонента будет выглядеть так:

<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}}
person aceofspades    schedule 17.05.2015
comment
Это может быть дополнительно упрощено, чтобы исключить необходимость в определениях объектов в компоненте. Используя надстройку ember-truth-helpers, вы можете использовать {{yield 'header'}} в шаблоне компонента, а затем {{#if (eq section 'header')}} в шаблоне потребителя. - person aceofspades; 21.09.2015

Предыдущий ответ может быть устаревшим.

Для этой проблемы существует принятый 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 — полный пример.

person ppcano    schedule 20.09.2018
comment
Это должен быть принятый ответ для Ember 2.x и 3.x. - person gy.om; 06.11.2018
comment
Кроме того, вместо жесткого кодирования полученных подкомпонентов родительский компонент my-component может принимать их в качестве параметров. - person gy.om; 06.11.2018