Vue.jsでSlotsの代わりにPropsを使用する理由、名前付きSlotsやスコープ付きSlotsとの違いについて解説
Post on:2020年11月4日
Vue.jsのコンポーネント間でデータを渡す方法はたくさんありますが、Propsを使うかSlotsを使うかはニーズによります。Slotsの代わりにPropsを使用する理由、名前付きSlotsやスコープ付きSlotsとの違いについて紹介します。
The Difference Between Props, Slots and Scoped Slots in Vue.js
by Luca Spezzano
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
私はVue.jsを使い始めた時は、コンポーネント間のデータをPropsを介して渡していましたが、使い続けていくと、Slotsでも同じ結果を得られることが分かりました。
Photo by Bianca Ackermann on Unsplash
この記事では、Slotsの代わりにPropsを使用する理由やその逆も含めて違いを解説します。
Vue.jsのprops
Vue.jsのPropsとは、親コンポーネントからのデータを受け入れるために公開される属性です。
propsを使用して、コンポーネントMyMessageを作成してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div class="message"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: "MyMessage", props: { msg: String, }, }; </script> <style scoped> .message { color: red; text-decoration: underline; } </style> |
コンポーネントはmsgという値を受け入れます。
このコンポーネントを使用すると、属性に値を渡すことができるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
<template> <my-message msg="NotOnlyCSS is awesome!" /> </template> <script> import MyMessage from "./components/MyMessage.vue"; export default { name: "App", components: { MyMessage, }, }; </script> |
デモページで、Propsの動作を確認できます。
Propsがどのように機能するかはこれで明らかだと思います。
Vue.jsのSlots
また、HTMLコードを使ってコンポーネントを作成することができます。
slotがあるコンポーネントMyMessageを作成してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<template> <div class="message"> <slot /> </div> </template> <script> export default { name: "MyMessage", }; </script> <style scoped> .message { color: red; text-decoration: underline; } </style> |
コンポーネントはSlotsを介してコードのブロックを受け入れます。
このコンポーネントを使用すると、親から次のようなものを渡すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<template> <my-message> <h1>NotOnlyCSS is awesome!</h1> <p>these are slots</p> </my-message> </template> <script> import MyMessage from "./components/MyMessage.vue"; export default { name: "App", components: { MyMessage, }, }; </script> |
デモページで、Slotsの動作を確認できます。
名前付きSlotsとの違い
特に複雑なコンポーネントの場合は、複数のSlotsがあると便利です。slot要素にname属性を使用して異なるスロットにidを割り当てることができます。
名前付きSlotsを持つコンポーネントMyMessageを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<template> <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <script> export default { name: "MyMessage", }; </script> <style scoped> header { color: red; text-decoration: underline; } footer { color: blue; } </style> |
このコンポーネントを使用すると、親から次のようなものを渡すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<template> <my-message> <template v-slot:header> <h1>NotOnlyCSS is awesome!</h1> </template> <template v-slot:default> <p>A paragraph for the component.</p> <p>And <b>another</b> one.</p> </template> <template v-slot:footer> <small>The footer of the component</small> </template> </my-message> </template> <script> import MyMessage from "./components/MyMessage.vue"; export default { name: "App", components: { MyMessage, }, }; </script> |
デモページで、名前付きSlotsの動作を確認できます。
Vue.jsを使用して毎日作業をしていると、少し複雑ですが非常に便利な別のタイプのSlotsを発見しました。スコープ付きSlotsと呼ばれるもので、どのように機能するかをよりよく理解することができます。
スコープ付きSlotsとの違い
親から子コンポーネントで利用可能なデータにアクセスできると便利な場合があります。その場合、スコープ付きSlotsが便利です。
スコープ付きSlotsを持つコンポーネントMyMessageを作成してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template> <div class="message"> <slot :firstName="firstName"></slot> </div> </template> <script> export default { name: "MyMessage", data() { return { firstName: "Luca", }; }, }; </script> <style scoped> .message { color: red; text-decoration: underline; } </style> |
親によって提供されたSlotコンテンツで値を利用できるようにするには、<slot>要素を追加して、属性としてバインドします。
これで、親コンポーネントからもfirstNameという値にアクセスできるようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<template> <my-message> <template v-slot="slotProps"> <h1>Hey {{ slotProps.firstName }}, NotOnlyCSS is awesome!</h1> </template> </my-message> </template> <script> import MyMessage from "./components/MyMessage.vue"; export default { name: "App", components: { MyMessage, }, }; </script> |
デモページで、スコープ付きSlotsの動作を確認できます。
スコープ付きSlotsがいつ役立つかについて考えているかもしれませんが、一般的なケースとしては、コンポーネントがアイテムの配列をレンダリングするために使用され、各アイテムのレンダリング方法をカスタマイズできるようにしたい場合です。
終わりに
Vue.jsのコンポーネント間でデータを渡す方法はたくさんありますが、Propsを使うかSlotsを使うかはニーズによります。Propsを使用すると子コンポーネントに値を渡すことしかできないので、親は子をカスタマイズすることができません。
定義済みのデザインがあり、いくつかの値を変更する必要がある場合は、Propsを使用してください。
Slotsを使用すると柔軟性が高まり、親から子コンポーネントをカスタマイズすることができます。
コンポーネントをカスタマイズする自由を親に与えたい場合は、Slotsを使用します!
sponsors