お世話になります。
デフォルトコンポーネントに用意されているSLOTを使えるようにvuetifyコンポーネントを拡張しようとしたとき、次のようなコーディングがWebで検索できます。
vue
1<template v-for="(value, name) in $scopedSlots" #:[name]="slotProps> 2 <slot :name="name" v-bind="slotProps /> 3</template>
親コンポーネントから受け取ったSLOTを、自身のSLOTに流し込んでいます。
ところが、デフォルトコンポーネントがスロットプロパティを用意していない場合、SLOTがうまく機能しません。
例)v-data-tableに上記のコーディングを追加したカスタムコンポーネントを作成すると、例えばno-dataスロットが機能しません。
vue
1<v-data-table> 2 <template v-for="(value, name) in $scopedSlots" #:[name]="slotProps"> 3 <slot :name="name" v-bind="slotProps" /> 4 </template> 5</v-data-table> 6<!-- topなどのスロットプロパティが用意されているSLOTは正常に機能する --> 7<!-- no-dataなどのスロットプロパティが用意されていないSLOTは機能しない -->
どうやら、スロットプロパティが用意されていない場合、「#:[name]="slotProps"」で異常となり、<template>がレンダリングされないようです。(Chromeのコンソールにエラーは吐き出されませんでした。)
試しにスロットプロパティが用意されていないSLOTの名前を配列で用意し、以下のようなコンポーネントを作ってみたところ、正常に機能しました。
vue
1<template> 2 <v-data-table> 3 <template v-for="scopedSlot in scopedSlots" #[scopedSlot]="slotProps"> 4 <slot :name="scopedSlot" v-bind="slotProps" /> 5 </template> 6 <template 7 v-for="scopedSlotWithoutProps in scopedSlotsWithoutProps" 8 #[scopedSlotWithoutProps] 9 > 10 <slot :name="scopedSlotWithoutProps"></slot> 11 </template> 12 </v-data-table> 13</template> 14 15<script> 16export default { 17 data() { 18 return { 19 slotsWithoutProps: ['loading', 'no-data', 'no-results', 'progress'], 20 } 21 }, 22 computed: { 23 scopedSlots() { 24 return Object.keys(this.$scopedSlots).filter( 25 (v) => !this.slotsWithoutProps.includes(v) 26 ) 27 }, 28 scopedSlotsWithoutProps() { 29 return Object.keys(this.$scopedSlots).filter((v) => 30 this.slotsWithoutProps.includes(v) 31 ) 32 }, 33 }, 34} 35</script> 36 37<style></style>
vuetifyコンポーネントの拡張という意味では実現できたので良いのですが、スマートな実装方法ではないような気がしています。
※変数名の付け方は別として。
もっとスマートなやり方はありませんでしょうか?
あなたの回答
tips
プレビュー