Vue.jsのslotを使ってみる

親側から子コンポーネントにテンプレートの一部を差し込める、slotという機能を使ってみます。

サンプルコード

navigation-linkという名前のコンポーネントを作成してみます。

Vue.component('navigation-link', {
  props: ['url'],
  template: `
    <a
      v-bind:href="url"
      class="nav-link"
    >
      <slot>指定がなかった場合の初期値</slot>
    </a>
  `
});

var app = new Vue({
  el: '#app',
});

8行目のslot部分が、コンポーネント使用時に設定する内容で置き換えることができます。
コンポーネント使用時に設定がなかった場合は、slotタグ内の記述内容(今回の場合は「指定がなかった場合の初期値」)が表示されます。

実際にコンポーネントを使ってみます。

<div id="app">
  <navigation-link url="/profile">
    <span>プロフィール</span>
  </navigation-link>
  <navigation-link url="/user"></navigation-link>
</div>

navigation-linkタグの中に記述した内容が前述のslotタグ部分と置き換わって描画されます。
slotのデモページ

slotを同一コンポーネント内で複数使用したい場合、name属性を使って名前を付けることができます。

Vue.component('base-layout', {
  template: `
    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
  `
});

var app = new Vue({
  el: '#app'
});

name属性のないslot(8行目)はdefaultという名前になります。

コンポーネント使用時は、templateタグに「v-slot:スロット名」の形で指定します。

<div id="app">
  <base-layout>
    <template v-slot:header>
      <h1>ヘッダー</h1>
    </template>

    <p>コンテンツ部分</p>

    <template v-slot:footer>
      <p>フッター</p>
    </template>
  </base-layout>
</div>

templateタグで囲っていない部分はdefaultになります。
名前付きslotのデモページ

slotの内容指定の際、親側のデータを指定することもできます。

<div id="app">
  未設定時:
  <current-user></current-user>
  親側のデータ指定:
  <current-user>
    <template>
      {{ name }}
    </template>
  </current-user>
</div>

JavaScript側の設定です。

Vue.component('current-user', {
  data: function () {
    return {
      user: {
        firstName: 'taro',
        lastName: 'suzuki'
      }
    }
  },
  template: `
    <span>
      <slot>
        {{ user.lastName }}
      </slot>
    </span>
  `
});

var app = new Vue({
  el: '#app',
  data: {
    name: 'tanaka'
  }
});

スコープのデモページ

ただ逆に、親側からコンポーネント内のデータにアクセスすることは通常できません。

<div id="app">
  <current-user>
    <template>
      {{ user.firstName }}
    </template>
  </current-user>
</div>

スコープのデモページ2

スコープ付きスロットという機能を使うことで、コンポーネント内のデータにアクセスできます。
使用したいデータ(今回の場合user)をslotタグの属性としてバインドします。

Vue.component('current-user', {
  data: function () {
    return {
      user: {
        firstName: 'taro',
        lastName: 'suzuki'
      }
    }
  },
  template: `
    <span>
      <slot v-bind:user="user">
        {{ user.lastName }}
      </slot>
    </span>
  `
});

var app = new Vue({
  el: '#app',
  data: {
    name: 'tanaka'
  }
});

templateタグで以下ように設定すると、子コンポーネントのデータを親で使用できます。

<div id="app">
  <current-user>
    <template v-slot:default="slotProps">
      {{ slotProps.user.firstName }}
    </template>
  </current-user>
</div>

slotProps部分はほかの名前でも大丈夫です。
スコープのデモページ3

参考サイト

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930