スロット

スロットを使用すると、子コンポーネント内の特定の場所に動的なコンテンツを挿入できます。
※テンプレートの柔軟性が向上し、コードの再利用性が高まる

スロット
記法

【親コンポーネント】
<template v-slof:スロット名> or <template #スロット名>
 +++++++++++
 スロット名の内容
 +++++++++++
</template>
 +++++++++++
 デフォルト内容
 +++++++++++

【子コンポーネント】
// スロット名の内容が反映
<slot name=”スロット名”></slot>
// デフォルト内容が反映
<slot></slot>

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>slotについて</title>
    <link rel="stylesheet" href="./main.css" />
  </head>
  <body>
    <div id="app"></div>

    <!-- CDN -->
    <script src="CDNのURL"></script>
    <script src="./main.js"></script>
  </body>
</html>
// 子コンポーネントを定義、デフォルトスロット、名前付きスロット、スコープ付きスロットを使用
const CustomComponent = {
  template: `
    <div class="custom-component">
      <slot>デフォルトのコンテンツです。</slot>
      <slot name="header"></slot>
      <slot name="footer"></slot>
      <div v-if="hasDetails">
        <slot name="details" :info="details"></slot>
      </div>
    </div>
  `,
  props: ["details"],
  computed: {
    hasDetails() {
      // !!によりブール値(true/false)に変換
      // 存在する場合true・存在しない場合falseを返す
      return !!this.details;
    },
  },
};

// カスタムコンポーネントを使用するためのメインVueインスタンスを作成
Vue.createApp({
  components: {
    "custom-component": CustomComponent,
  },
  data() {
    return {
      details: {
        title: "詳細情報のタイトル",
        content: "これは詳細情報のコンテンツです。",
      },
    };
  },
  template: `
    <div>
      <custom-component :details="details">
        <template #header>
          <p class="header">ヘッダーのコンテンツ</p>
        </template>
        <template #footer>
          <p class="footer">フッターのコンテンツ</p>
        </template>
        <p>このコンテンツはデフォルトスロットに挿入されます。</p>
        <template #details="{ info }">
          <div class="details">
            <p>{{ info.title }}</p>
            <p>{{ info.content }}</p>
          </div>
        </template>
      </custom-component>
    </div>
  `,
}).mount("#app");
.custom-component {
  border: 1px solid #ccc;
  padding: 20px;
  margin: 20px;
}
.header {
  font-weight: bold;
  color: blue;
}
.footer {
  font-style: italic;
  color: gray;
}
.details {
  background-color: #f9f9f9;
  border: 1px solid #ddd;
  padding: 10px;
  margin-top: 10px;
}
出力結果