LoginSignup
12
4

More than 3 years have passed since last update.

Vue.js Slotの使い方

Last updated at Posted at 2020-09-16

Vue.jsのスロットについて使い方が曖昧だったので、公式ドキュメントから自分なり咀嚼してまとめる。

slotとは

受け取った子コンポーネントに親コンポーネントから要素の受け渡しができる。

子コンポーネント<slot></slot>の部分に親コンポーネントで渡した要素が入る

navigationLink.vue
<template>
 <a href= "https://www.google.com/"
  class="nav-link">
  <slot></slot>
</a>
</template>

Parent.vue
<template>
  <div id="app">
    <navigationLink>
      Googleへのリンク
    </navigationLink>
  </div>
</template>

結果
Image from Gyazo
もしも <navigationLink> のテンプレートが 要素を含まない場合、開始タグと終了タグの間にある任意のコンテンツは破棄される。
この場合だと、Googleへのリンクは破棄され、何も描画されなくなる

・スロットには任意のタグや他のコンポーネントを埋め込むことが出来る

Parent.vue
<template>
 <!--ボタンタグを埋め込み-->
 <navigationLink>
  <button>Googleへのリンク</button>
 </navigationLink>

<!--コンポーネントの埋め込み-->
 <navigationLink>
  <List />
 </navigationLink>
</template>

フォールバックコンテンツ

フォールバックとは、通常使用する方式や系統が正常に機能しなくなったときに、機能や性能を制限したり別の方式や系統に切り替えるなどして、限定的ながら使用可能な状態を維持すること。 また、そのような切り替え手順・動作のこと
参考:IT用語辞典 e-Words

つまり、子コンポーネントのButtonタグの間に何も記述がなかった場合、切り替え手順として<slot>タグ間に設定してあるSubmitが描画される

Button.vue
<template>
<button type="submit">
  <slot>Submit</slot>
</button>
</template>
Parent.vue
<template>
  <div id="app">
 <!--Submitが表示される-->
  <Button></Button>
  <!--送信が表示される-->
  <Button>送信</Button>
  </div>
</template>

名前付きスロット

複数のスロットを使う際に、名前を付けて場合分けをする
名前付きスロットを使う場合は<template>タグで囲い、v-slotで名前をつける
今回は<template v-slot:header>とする
子コンポーネントでは<slot name="header">のように指定する
<template>タグで囲っていない要素は名前なしの<slot>に入る

Parent.vue
 <div id="app">
   <baseLayout>
    <!-- <slot name="header" />に入る -->
    <template v-slot:header>
     <h1>Here might be a page title</h1>
    </template>

   <!-- 名前なしslotに入る -->
     <p>A paragraph for the main content.</p>
     <p>And another one.</p>

   <!-- <slot name="footer" />に入る -->
    <template v-slot:footer>
     <p>Here's some contact info</p>
    </template>
   </baseLayout>
  </div>
baseLayout.vue
 <div class="container">
  <header>
  <!-- 親コンポーネントのv-slot:headerの要素を受け取る -->
    <slot name="header" />
  </header>
  <main>
    <!-- 名前を付けない場合はtemplete外の要素を受け取る -->
    <slot></slot>
  </main>
  <footer>
    <!-- 親コンポーネントのv-slot:footerの要素を受け取る -->
    <slot name="footer"></slot>
  </footer>
</div>

名前なしを明示的に指定したい場合は
<template v-slot:default>のようにdefaultをつける

コンパイルスコープ

このスロットはParent.vue内のdataにアクセス出来る。
navigationLink.vueのスコープにはアクセス出来ない。

Parent.vue
<template
 <navigationLink>
   {{user.lastName}}
 </navigationLink>

<!-- 省略 -->
<script>
data(){
    return{
      user:{lastName:"yamada",firstName:"taro"}
    }
  }
</script>

スコープ付きスロット

親コンポーネント側から子コンポーネントのデータにアクセスしたい場合<slot> 要素に属性を指定してバインドする

currentUser.vue
<template>
<span>
  <!-- dataのusreをバインドして親コンポーネントからアクセス -->
  <slot :user="user">
    {{ user.lastName }}
  </slot>
</span>
</template>
<script>
export default {
  data(){
    return {
      user:{lastName:"tanaka",firstName:"jiro"}
    }
  }
}
</script>
Parent.vue
 <currentUser>
    <!-- slotPropsは任意の値 -->
  <template v-slot:default="slotProps">
    <!-- 子コンポーネントのuserにアクセス -->
    {{ slotProps.user.firstName }}
  </template>
 </currentUser>
<!-- 省略記法 -->
<!-- 名前なしスロットのみの場合コンポーネントタグをスロットのテンプレートとして使うことができる -->
<!-- ただし、名前付きスロットと混在は不可。複数slotがある場合は<template>を使う -->
  <currentUser v-slot="slotProps">
    {{ slotProps.user.firstName }}
  </currentUser>

<!---分割代入を使った記法 -->
 <currentUser v-slot="{ user }">
    {{ user.firstName }}
 </currentUser>

<!---分割代入はプロパティをリネームする事もできる -->
<currentUser v-slot="{ user:person }">
   {{ person.firstName }} 
</currentUser>

動的なスロット名

スロット名は動的に定義が可能。
例えばdataからスロット名を定義できる

baseLayout.vue
<div>
  <slot name="slotName"></slot>
</div>
Parent.vue
<baseLayout> 
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</baseLayout>
<!-- 省略 -->
<script>
 data(){
    return{
      dynamicSlotName:"slotName"
    }
  }
</script>

名前付きスロットの省略記法

v-slotは省略があり#で置き換えられる。
例えばv-slot:header#headerに書き換えられる
名前なしスロットで省略記法を使いたい場合はdefaultでスロット名を指定する必要がある

Parent.vue
<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>

参考: https://vuejs.org/v2/guide/components-slots.html

12
4
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
12
4