🦉 Разнообразие(Miscellaneous) 🦉

Содержание

Portal

Введение

Компонент Portal предназначен для использования в качестве прозрачного способа телепортировать часть DOM в узел, представленный его единственными целевым пропсом.

Этот компонент помогает реализовать необходимую инфраструктуру для модальных окон (например, bootstrap-modal).

Использование

Содержимое, которое он будет телепортировать, определяется в узле <Portal> и внутренне использует defaultSlot.

Этот слот должен содержать только один узел, который, в свою очередь, может иметь столько дочерних элементов, сколько необходимо.

Элемент, под которым будет телепортироваться контент, представлен как селектор пропсами target, которые принимают только строку в качестве значения.

Реквизит target поддерживает только статический селектор и не предназначен для передачи в Portal в качестве переменной. А именно, <Portal target="'body'" /> является предполагаемым использованием. Напротив, <Portal target="state.target" /> не поддерживается.

Компонент Portal не имеет определенного состояния, скорее, он должен быть ведомым для своего родителя и, в конечном счете, просто способом для родителя телепортировать часть своей DOM в другое место.

Корневым узлом портала всегда является , и он размещается там, где должен быть_ телепортированный контент. Именно на этот элемент перенаправляются телепортированные события.

Пример

Канонический вариант использования заключается в реализации Dialog, где компонент может прервать естественный рабочий процесс, чтобы помочь пользователю ввести некоторые данные, которые он мог бы использовать позже.

JavaScript:

const { Component, mount } = owl;
const { Portal } = owl.misc;

class TeleportedComponent extends Component {}
class App extends Component {
  static components = { Portal, TeleportedComponent };
}

mount(App, { target: document.body });

XML:

<templates>
    <div t-name="TeleportedComponent">
        <span>Я перееду достаточно скоро</span>
    </div>

    <div t-name="App">
        <span>Я такой же как и все мы</span>
        <Portal target="'body'">
            <TeleportedComponent />
        </Portal>
    </div>
</templates>

В этом примере компонент Portal будет телепортировать div TeleportedComponent как дочерний элемент body. TeleportedComponent действует здесь как Dialog.

Результирующий DOM будет выглядеть так:

<body>
    <div>
        <span>Я такой же как и все мы</span>
        <portal></portal>
    </div>
    <div>
        <span>Я перееду достаточно скоро</span>
    </div>
</body>

Ожидаемое поведение

Телепортированная часть обновляется как DOM любого другого Component и в той же последовательности. А именно, телепортированная часть будет обновлена ​​в зависимости от своих родительских компонентов и исправлена ​​как обычный дочерний элемент.

_business_события, инициированные дочерним компонентом, будут остановлены, чтобы не выходить за пределы target. С другой стороны, они будут перенаправлены на корневой узел Portal и поднимает DOM, как если бы он был вызван обычным дочерним компонентом.

Помните, что эти перенаправленные события являются копиями исходного события. У них есть:

  • Та же полезная нагрузка.
  • Тот же originalComponent, что и их оригинальный аналог, то есть фактический Component, который его запустил.
  • отличное target свойство, чем их исходный аналог. target перенаправленного события обязательно является корневой узел Portal.

Чистые DOM-события не следуют этому шаблону и могут свободно подниматься естественным, неизмененным путем вверх к «телу».

AsyncRoot

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

<div t-name="ParentComponent">
  <SyncChild />
  <AsyncRoot>
     <AsyncChild/>
  </AsyncRoot>
</div>

AsyncRoot предполагает, что внутри него находится ровно один корневой узел. Это может быть узел dom или компонент.