Vue.jsのスロットを使った柔軟なコンポーネント設計

Vue.jsのスロットを使った柔軟なコンポーネント設計

Vue.jsのスロット機能を活用すると、コンポーネントを柔軟かつ再利用可能に設計できます。スロットは、コンポーネントの中に動的にコンテンツを挿入するための強力な仕組みです。この記事では、基本的なスロットから高度な使い方までを網羅し、効果的なコンポーネント設計を解説します。

スロットとは

スロットは、親コンポーネントから子コンポーネントにHTMLコンテンツやVueテンプレートを挿入するための仕組みです。

<template>
  <div>
    <slot></slot>
  </div>
</template>

基本的なスロットの使用

親コンポーネントから子コンポーネントに任意のHTMLを渡すことができます。

// 子コンポーネント
<template>
  <div>
    <h1>タイトル</h1>
    <slot></slot>
  </div>
</template>

// 親コンポーネント
<ChildComponent>
  <p>この内容はスロットを通じて表示されます。</p>
</ChildComponent>

デフォルトコンテンツ

スロットに何も渡されなかった場合のデフォルトコンテンツを設定できます。

<template>
  <div>
    <slot>デフォルトのコンテンツ</slot>
  </div>
</template>

名前付きスロット

複数のスロットを持つコンポーネントでは、`name`属性を使用して異なる内容を挿入できます。

// 子コンポーネント
<template>
  <div>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
  </div>
</template>

// 親コンポーネント
<ChildComponent>
  <template v-slot:header>
    <h2>ヘッダー部分</h2>
  </template>
  <p>メインコンテンツ</p>
</ChildComponent>

スコープ付きスロット

子コンポーネントからデータをスロット経由で親コンポーネントに渡すことができます。

// 子コンポーネント
<template>
  <div>
    <slot :item="item"></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      item: { name: 'Vue.js' }
    };
  }
};
</script>

// 親コンポーネント
<ChildComponent v-slot="{ item }">
  <p>{{ item.name }}</p>
</ChildComponent>

デフォルトスコープ付きスロット

デフォルトのスロットでもスコープ付きデータを渡すことができます。

<template>
  <div>
    <slot :user="user"></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: { name: 'John' }
    };
  }
};
</script>

動的なスロット名

動的にスロット名を切り替えることが可能です。

// 子コンポーネント
<template>
  <div>
    <slot :name="currentSlot"></slot>
  </div>
</template>

// 親コンポーネント
<ChildComponent :currentSlot="'header'">
  <template v-slot:header>
    <p>動的ヘッダー</p>
  </template>
</ChildComponent>

複数のスコープ付きスロット

複数のスコープ付きスロットを使用することができます。

// 子コンポーネント
<template>
  <div>
    <slot name="item" :item="item"></slot>
    <slot name="footer" :info="info"></slot>
  </div>
</template>

スロットのデータ流れ

子コンポーネントからスロット経由でデータを渡す際、適切に`v-slot`を使用することが重要です。

// 親コンポーネント
<ChildComponent v-slot:item="{ item }">
  <p>{{ item.name }}</p>
</ChildComponent>

コンポジションAPIとの併用

コンポジションAPIとスロットを組み合わせることで、より柔軟なデータフローが可能です。

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

<template>
  <ChildComponent v-slot="{ item }">
    <p>{{ item.name }}</p>
  </ChildComponent>
</template>

ユースケース例: 汎用カードコンポーネント

スロットを使用して再利用可能なカードコンポーネントを設計します。

// Card.vue
<template>
  <div class="card">
    <header><slot name="header"></slot></header>
    <main><slot></slot></main>
    <footer><slot name="footer"></slot></footer>
  </div>
</template>

// 使用例
<Card>
  <template #header>カードヘッダー</template>
  <p>カード本文</p>
  <template #footer>カードフッター</template>
</Card>

パフォーマンスへの考慮

複数のスロットや動的なスロットを多用する場合、レンダリングコストに注意し、必要な部分だけを動的にレンダリングするように心掛けましょう。

まとめ

Vue.jsのスロット機能を適切に活用することで、コンポーネントの柔軟性と再利用性が向上します。基本的なスロットからスコープ付きスロット、動的スロットまで理解し、効果的なコンポーネント設計を行いましょう。