Vueのslotについて
直近でやっているタスクでVueのslotの使い方で少しハマってしまったところがあったので自分用にまとめてみます。
以下全てVue2系の話です。
slotの基本
子コンポーネントに親コンポーネントから要素を渡すことができます。
たとえば、
<template> <div> <slot /> </div> </template> <script> export default { name: 'hoge' } </script>
<template> <hoge> fugafuga </hoge> </template> <script> import hoge from './hoge' export default { name: 'fuga', components: { hoge } } </script>
このような形で渡すことができます。<slot />
の部分にはfugafuga
という文字列が入ります。
<template> <hoge> <piyo /> </hoge> </template> <script> import hoge from './hoge' import piyo from './piyo' export default { name: 'fuga', components: { hoge, piyo } } </script>
こんな感じでコンポーネントを渡すこともできます。
名前付きslot
複数のslotを使いたい場合、各スロットに名前をつけることができます。
<template> <div> <slot name="title" /> <slot name="body" /> </div> </template> <script> export default { name: 'hoge' } </script>
このようにすると、
<template> <hoge> <template #title> title </template> <template #body> body </template> </hoge> </template> <script> import hoge from './hoge' export default { name: 'fuga', components: { hoge } } </script>
こうするとtitleとbodyがそれぞれ指定したslotに入ります。
#title
は省略記法で省略せずに書くとv-slot:title
になります。
また、nameの無いslotには暗黙的にdefault
という名前が付きます。
スコープ付きslot
親コンポーネントからslotのプロパティにアクセスできるようにするには以下のようにbindします。
<template> <div> <slot :title="title" /> </div> </template> <script> export default { name: 'hoge', data() { return { title: 'hogehoge' } } } </script>
そして親コンポーネント側で以下のようにします。
<template> <hoge> <template #title="slotProps"> {{ slotProps.title }} </template> </hoge> </template> <script> import hoge from './hoge' export default { name: 'fuga', components: { hoge } } </script>
slotProps
は任意の名前でOKです。
名前付きslotが無い場合は#title
となっているところをv-slot:default (#default)
またはv-slot
とすれば対応できます。
イベントハンドラ
slotに対してイベントハンドラを直接設定することはできません。
<template> <div> <slot @click="title = 'hogefuga'" /> </div> </template> <script> export default { name: 'hoge', data() { return { title: 'hogehoge' } } } </script>
↑はできないということです。
こちらでも言及されています。
You cannot listen to events on <slot>. It can end up rendering anything: text, plain element, multiple nodes... the behavior will be unpredictable.
なので、イベントハンドラを設定する場合は親コンポーネントで設定するようにします。
<template> <hoge @click="title = 'hogefuga'"> <template> {{ title }} </template> </hoge> </template> <script> import hoge from './hoge' export default { name: 'fuga', components: { hoge }, data() { return { title: 'hogehoge' } } } </script>
ここで詰まってしまって思った以上に時間を取られてしまいました。
まとめ
以上Vueのslotについてまとめてみました。
slotを使うとき若干混乱しがちなので改めて整理してみて良かったと思います。
便利な機能であることは間違いないので上手く活用していきたいです。