0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vueのスロット入門から実践へ:Vuetifyのv-data-tableで関数付きスロットを活用する方法

Last updated at Posted at 2025-05-17

Vueのスロット(slot)を理解してVuetifyの関数付きスロット活用へつなげる実践例:v-data-tableで行操作を柔軟にカスタマイズ

Vueには「スロット(slot)」という仕組みがあり、親コンポーネントが子コンポーネントにテンプレートを差し込むことで、柔軟なコンポーネント設計ができます。

この記事では、まず Vueのスロットの基本構文と考え方を解説し、その後、VuetifyのUIコンポーネントでスロットを活用する実践例として、v-data-tableで関数をスロット経由で使って行操作する方法を紹介します。


スロットとは?

スロットは、Vueで親コンポーネントが子コンポーネントにテンプレート(HTML)やロジック(変数・関数)を渡すための仕組みです。

例:デフォルトスロット

<!-- 子コンポーネント -->
<template>
  <div class="card">
    <slot></slot> <!-- 親からのコンテンツをここに挿入 -->
  </div>
</template>

<!-- 親コンポーネント -->
<MyCard>
  <p>これはカードの中身です。</p>
</MyCard>

スコープ付きスロット

スロットに値や関数を渡したい場合、スコープ付きスロットを使います。

<!-- 子コンポーネント -->
<template>
  <slot :count="count" :increment="increment"></slot>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => { count.value++ }
</script>

<!-- 親コンポーネント -->
<MyCounter v-slot="{ count, increment }">
  <p>現在のカウント: {{ count }}</p>
  <button @click="increment">カウントアップ</button>
</MyCounter>

Vuetifyのスロット活用へ

Vuetifyの多くのコンポーネントでも、スロットから関数や状態を受け取れる「スコープ付きスロット」が提供されています。

代表的な例が v-data-tableitem スロットです。


実践:v-data-table でスロットから関数を受け取り、行を操作する

目標

  • スロットから Vuetify が提供する関数(isSelected, toggleSelect)を受け取って行の選択状態を制御する
  • 各行に「削除」ボタンを追加して独自の操作を実装する

実装例

<template>
  <v-data-table
    :items="desserts"
    item-value="name"
    show-select
    v-model:selected="selected"
  >
    <!-- itemスロット:各行のカスタム描画 -->
    <template #item="{ item, isSelected, toggleSelect }">
      <tr :style="{ backgroundColor: isSelected(item) ? '#f0f0f0' : '' }">
        <td>
          <v-btn icon @click="toggleSelect(item)">
            <v-icon>
              {{ isSelected(item) ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }}
            </v-icon>
          </v-btn>
        </td>
        <td>{{ item.name }}</td>
        <td>{{ item.calories }}</td>
        <td>
          <v-btn color="error" @click="removeItem(item)">削除</v-btn>
        </td>
      </tr>
    </template>
  </v-data-table>
</template>

<script setup>
import { ref } from 'vue'

const selected = ref([])

const desserts = ref([
  { name: 'プリン', calories: 300 },
  { name: 'アイスクリーム', calories: 200 },
  { name: 'ケーキ', calories: 400 },
])

const removeItem = (item) => {
  desserts.value = desserts.value.filter(d => d.name !== item.name)
}
</script>

#は何の略?(v-slotの省略記法)

Vueでは、スロットを使うときに v-slot: というディレクティブを指定できます。たとえば:

<template v-slot:item>
  カスタム行
</template>

この v-slot: は、Vue 2.6 以降で導入された構文で、以下のように # に省略して書くことができます:


<template #item>
  カスタム行
</template>

Vuetifyのドキュメントではスロット名が item.data-table-expand のように書かれていますが、Vueテンプレート内では #item.data-table-expand のように使用します。


Vuetifyのドキュメントからの読み解き方

Vuetifyの公式ドキュメントに記載されているスロット名(例:item.${string}header.${string})は、そのままVueテンプレートの#item.カラム名 のように変換して使えます

例:

  • item.${string}<template #item.name><template #item.calories> のように使用(カラム名に対応)
  • item.data-table-expand<template #item.data-table-expand>
  • header.${string}<template #header.name>

つまり、item.${string}header.${string} のような表記は、カラム名ごとのセル/ヘッダーのカスタマイズが可能という意味です。

このように、Vuetifyのドキュメントを見ながら、スロット名に # をつけ、${string} の部分を実際のカラムキーに置き換えるだけで、目的のカスタマイズができるようになります。


まとめ

  • Vueのスロットは、テンプレートの差し込みだけでなく値や関数も親に渡せる強力な仕組み
  • Vuetifyでは、多くのコンポーネントがスコープ付きスロットを通じて関数や状態を提供している
  • ドキュメントのスロット名(例:item.${string})に # をつけて ${string} を実際のカラムキーに置き換えれば Vueテンプレートで使用可能
  • v-data-tableitem, item.${string}, header.${string} などは、行やセル単位での柔軟な描画カスタマイズが可能

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?