Иногда возникает необходимость определить в компоненте несколько слотов, которые могли бы иметь
разное содержимое. В этом случае каждому слоту можно назначить определенное имя и через это имя передавать в него некоторый контент из родительского компонента.
Для этого в элементе <slot>
используется атрибут name.
Например, определим следующую веб-страницу:
<!DOCTYPE html> <html> <head> <title>Слоты Vue 3</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <container> <template v-slot:header> <h1>Заголовок статьи</h1> </template> <template v-slot:default> <p>Первый абзац.</p> <p>Второй абзац.</p> </template> <template v-slot:footer> <p>Для более подробной информации напишите по адресу contacts@gmail.com</p> </template> </container> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('container', { template: `<div> <header> <slot name="header"></slot> </header> <article> <slot></slot> </article> <footer> <slot name="footer"></slot> </footer> </div>` }); app.mount('#app'); </script> </body> </html>
Компонент container определяет ряд слотов. Причем один из слотов является обычным, а остальные два - именованными. Элементы <slot>
, у которых явным образом не установлено имя (то еть атрибут name),
по умолчанию имеют имя "default".
<div> <header> <slot name="header"></slot> </header> <article> <slot></slot> </article> <footer> <slot name="footer"></slot> </footer> </div>
То есть дочерний компонент определяетт структуру расположения контента. В родительском компоненте для слотов передается содержимое, которое
оборачивается в элемент <template>
. У этого элемента атрибут v-slot
принимает имя слота, на место которого
необходимо вставить содержимое.
<div id="app"> <container> <template v-slot:header> <h1>Заголовок статьи</h1> </template> <template v-slot:default> <p>Первый абзац.</p> <p>Второй абзац.</p> </template> <template v-slot:footer> <p>Для более подробной информации напишите по адресу contacts@gmail.com</p> </template> </container> </div>
Например, содержимое элемента <template v-slot:header>
будет вствляться на место слота с именем header, а элемент
<template v-slot:default>
предоставляет контент для слота без имени (по умолчанию имя default).
То есть в итоге сформируется следующая разметка:
<div> <header> <h1>Заголовок статьи</h1> </header> <main> <p>Первый абзац.</p> <p>Второй абзац.</p> </main> <footer> <p>Для более подробной информации напишите по адресу contacts@gmail.com</p> </footer> </div>
Также в дочернем компоненте можно предоставить контент по умолчанию, если родительский контейнер не предоставил для слотов никакого содержимого:
<!DOCTYPE html> <html> <head> <title>Слоты Vue 3</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <container> <template v-slot:default> <p>Первый абзац.</p> <p>Второй абзац.</p> </template> </container> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({}); app.component('container', { template: `<div> <header> <slot name="header"><h2>Заголовок по умолчанию</h2> <p>Дата статьи: {{ new Date().toLocaleDateString() }}</p></slot> </header> <article> <slot></slot> </article> <footer> <slot name="footer"><h5>Copyright©2020</h5></slot> </footer> </div>` }); app.mount('#app'); </script> </body> </html>