Слоты предоставляют механизм создания фиксированной структуры компонента, в которой содержимое для различных частей компонента определяет родительский компонент. Во Vue 3 слоты реализуются через элемент <slot>, вместо которого родительский компонент вставляет содержимое в дочерний компонент.
Рассмотрим следующий пример:
<!DOCTYPE html> <html> <head> <title>Слоты Vue 3</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <child-component><h2>Vue App</h2></child-component> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('child-component', { template: `<div> <h3>Child Component</h3> </div>` }); app.mount('#app'); </script> </body> </html>
Здесь в коде html внутри элемента <child-component>
, который представляет дочерний компонент, определено некоторое
содержимое, а именно заголовок h2:
<child-component><h2>Vue App</h2></child-component>
Однако при рендеринге Vue полностью заменяет этот элемент со всем его содержимым на шаблон компонента, определенный параметром template:
То есть в данном случае код родительского компонента, в данном сучае приложения Vue, помещенный внутрь элемента дочернего компонента, никак не влияет на
рндеринг. Теперь применим слоты. Для их применения в произольном месте шаблона дочернего компонента вставляется элемент <slot></slot>
:
<div id="app"> <child-component><h2>Vue App</h2></child-component> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('child-component', { template: `<div> <slot></slot> <h3>Child Component</h3> </div>` }); app.mount('#app'); </script>
При рендеринге вместо элемента slot в шаблоне дочернего компонента будет помещаться тот контент, который передал родительский компонент в дочерний -
в данном случае это заголовок h2 <h2>Vue App</h2>
:
При этом содержимое, помещаемое в слоты, может быть более сложным, нежели один элемент (как в даном случае заголовок h2), то есть этом может быть
группа элементов. Кроме того, в шаблоне дочернего компонента мы можем много раз использовать элемент <slot>
, и все эти вставки будут
заменяться контентом, переданным из родительского компонента:
<div id="app"> <child-component><h2>Vue App</h2><p>Это приложение Vue 3</p></child-component> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('child-component', { template: `<div> <slot></slot> <h3>Child Component</h3> <slot></slot> </div>` }); app.mount('#app'); </script>
Может иметь место ситуация, когда родительский комопонент не предоставляет для дочернего никакого содержимого для слота в дочернем компоненте. В этом случае дочерний компонент может определить некоторое содержимое по умолчанию:
<!DOCTYPE html> <html> <head> <title>Слоты Vue 3</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <ads></ads> <ads> <div> <p>Открыт набор на бесплатные курсы Udacity.</p> <p>Заявки принимаются до 16 октября</p> </div> </ads> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('ads', { template: `<div> <h3>Объявление</h3> <slot>Здесь могла бы быть ваша реклама</slot> </div>` }); app.mount('#app'); </script> </body> </html>
Здесь определен компонент ads, который представляет блок под рекламное объявление. Само рекламное объявление будет добавляться в компонент через элемент <slot>
.
При этом на момент определения компонента мы можем не знать, а будет ли предоставлять какое-либо содержимое. Поэтому мы можем определить в элементе <slot>
некоторое содержимое по умолчанию.
<slot>Здесь могла бы быть ваша реклама</slot>
При использовании компонента мы можем вложить в него некоторый контент, который будет вставляться в элемент <slot> и заменять в нем содержимое по умолчанию:
<div id="app"> <ads></ads> <ads> <div> <p>Открыт набор на бесплатные курсы Udacity.</p> <p>Заявки принимаются до 16 октября</p> </div> </ads> </div>
Причем в первом случае в компонент ads не передается никакого контента, поэтому первый компонент ads будет использовать для slot содержимое по умолчанию.
Второй же компонент ads принимает контент и заменяет им содержимое в элементе <slot>.