スロットについて
スロットとは?
親コンポーネント側で子コンポーネントの表示内容をガチャガチャやるための仕組み
名前付きスロット
子コンポーネント
<template lang="pug"> div slot(name="header") p header(slotの中身はフォールバックコンテンツ・指定がなければこの内容を表示) slot(name="body") p body(slotの中身はフォールバックコンテンツ・指定がなければこの内容を表示) slot(name="footer") p footer(slotの中身はフォールバックコンテンツ・指定がなければこの内容を表示) </template> <script lang="ts"> import {defineComponent} from 'vue'; export default defineComponent({ name: 'SlotChild', }); </script>
親コンポーネント
<template lang="pug"> div SlotChild template(v-slot:header) h1 「v-slot:」でスロットの名前を指定 template(#body) h1 「v-slot:」は「#」に置き換え可能 </template> <script lang="ts"> import {defineComponent} from 'vue'; import SlotChild from '@/components/SlotChild.vue'; export default defineComponent({ name: 'SlotParent', components: { SlotChild, }, }); </script>
スコープ付きスロット
基本的には親コンポーネントから子コンポーネント側のデータにアクセスしようとすると、エラー(TypeError: _ctx.user is undefined)となる。
子コンポーネント
<template lang="pug"> div slot(name="id") p {{user.id}} slot(name="name") p {{user.lastName}} </template> <script lang="ts"> import {defineComponent} from 'vue'; export default defineComponent({ name: 'SlotChild', setup() { const user = { id: 100, firstName: 'Jack', lastName: 'Daniels', }; return { user, }; }, }); </script>
親コンポーネント
<template lang="pug"> div SlotChild template(#name) // - "user"って誰やねんと怒られる h1 {{user.firstName}} </template> <script lang="ts"> import {defineComponent} from 'vue'; import SlotChild from '@/components/SlotChild.vue'; export default defineComponent({ name: 'SlotParent', components: { SlotChild, }, }); </script>
そこで登場するのがスロットプロパティ
アクセスさせるにはまず子コンポーネント側でslot要素の属性としてデータをバインドする。 そして、親コンポーネント側で"v-slot"の値として名前を指定すると、その名前でバインドしたデータにアクセスできるようになる。 また、名前を指定する際に分割代入を使用することで直接バインドしたデータにアクセスすることもできる。
子コンポーネント
<template lang="pug"> div slot(name="id") p {{user.id}} slot(name="name", :touchme="user") //- "touchme"という変数で"user"へのアクセスを許可する p {{user.lastName}} </template> <script lang="ts"> import {defineComponent} from 'vue'; export default defineComponent({ name: 'SlotChild', setup() { const user = { id: 100, firstName: 'Jack', lastName: 'Daniels', }; return { user, }; }, }); </script>
親コンポーネント
<template lang="pug"> div SlotChild template(v-slot:name="slotProps") // - "slotProps"がスロットプロパティです h1 {{slotProps.touchme.firstName}} SlotChild template(#name="{touchme}") // - 分割代入すれば直接"touchme"へアクセスできる h1 {{touchme.firstName}} </template> <script lang="ts"> import {defineComponent} from 'vue'; import SlotChild from '@/components/SlotChild.vue'; export default defineComponent({ name: 'SlotParent', components: { SlotChild, }, }); </script>