🦉 Слоты(Slots) 🦉

Содержание

Введение

Owl — это система компонентов, основанная на шаблонах. Следовательно, необходимо иметь возможность создавать универсальные компоненты. Например, представьте себе общий компонент Dialog, который может отображать произвольное содержимое.

Очевидно, мы хотим использовать этот компонент везде в нашем приложении, чтобы отображать различный контент. Компонент Dialog технически является владельцем своего содержимого, но является только контейнером. Пользователь Dialog — это компонент, который хочет внедрить что-то внутри Dialog. Именно для этого и нужны слоты.

Пример

Для создания универсальных компонентов полезно иметь возможность родительскому компоненту внедрять некоторый дочерний шаблон, но при этом оставаться владельцем. Например, общий диалоговый компонент должен отображать контент, нижний колонтитул, но с родителем в качестве контекста рендеринга.

Слоты вставляются директивой t-slot:

<div t-name="Dialog" class="modal">
  <div class="modal-title"><t t-esc="props.title"/></div>
  <div class="modal-content">
    <t t-slot="content"/>
  </div>
  <div class="modal-footer">
    <t t-slot="footer"/>
  </div>
</div>

Слоты определяются вызывающей стороной с помощью директивы t-set-slot:

<div t-name="SomeComponent">
  <div>some component</div>
  <Dialog title="'Some Dialog'">
    <t t-set-slot="content">
      <div>hey</div>
    </t>
    <t t-set-slot="footer">
      <button t-on-click="doSomething">ok</button>
    </t>
  </Dialog>
</div>

В этом примере компонент Dialog будет рендерить слоты content и footer с его родителем в качестве контекста рендеринга. Это означает, что нажатие на кнопку вызовет выполнение метода doSomething для родителя, а не для диалога.

Примечание. Ранее Owl использовала директиву t-set для определения содержимого слота. Такой подход объявлен deprecated(устаревшим) и больше не должен использоваться в новом коде.

Описание элементов

Слот по умолчанию

Первый элемент внутри компонента, который не является именованным слотом, будет считаться default слотом по умолчанию. Например:

<div t-name="Parent">
  <Child>
    <span>какое то содержимое</span>
  </Child>
</div>

<div t-name="Child">
  <t t-slot="default"/>
</div>

Содержимое по умолчанию

Слоты могут определять содержимое по умолчанию, если родитель их не определил:

<div t-name="Parent">
  <Child/>
</div>

<span t-name="Child">
  <t t-slot="default">содержимое по умолчанию</t>
</span>
<!-- будет отрендерен как: <div><span>содержимое по умолчанию</span></div> -->

Контекст рендеринга: содержимое слота фактически рендерится с контекстом рендеринга, соответствующему тому, где он было определен, а не тому, где он расположе. Это позволяет пользователю определять обработчики событий, которые будут привязаны к правильному компоненту (обычно к прародителю содержимого слота).

Динамические слоты

Директива t-slot фактически может использовать любые выражения, используя интерполяцию строк:

 <t t-slot="{{current}}" />