1
0

More than 3 years have passed since last update.

【Vue.js】slotについて

Posted at

親コンポーネントから子コンポーネントに、htmlごとデータを送る。

App.vue
<template>
  <div>
    <likeHeader>
      <h1>{{ word }}</h1>
    </likeHeader>
  </div>
</template>

<script>
import likeHeader from "./components/likeHeader.vue";

export default {
  name: "App",
  data() {
    return {
      word: "スロットを通じて送られました",
    };
  },
  components: {
    likeHeader,
  },
};
</script>
likeHeader.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
</script>

親コンポーネントのカスタムタグで囲まれた部分が、子コンポーネントのslotタグで囲まれた部分に送られる。

slotのスコープについて

実際に記載しているファイルにスコープが発生している。例えば下記のように、親コンポーネントのカスタムタグに子コンポーネント定義しているchildを渡しても、読み込むことはできない。

App.vue
<template>
  <div>
    <likeHeader>
      <h1>{{ child }}</h1>
    </likeHeader>
  </div>
</template>

<script>
import likeHeader from "./components/likeHeader.vue";

export default {
  components: {
    likeHeader,
  },
};
</script>
likeHeader.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      child: "子で定義",
    };
  },
};
</script>

結果、未定義エラーとなる。

[Vue warn]: Property or method "child" is not defined on the instance 
but referenced during render. Make sure that this property is reactive, 
either in the data option, or for class-based components, 
by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

ただし、styleタグについては、親コンポーネント子コンポーネントどちらに定義しても反映される。また、親と子に同一の定義があった場合は、

App.vue
<style>
h1 {
  color: red;
}
</style>
likeHeader.vue
<style>
h1 {
  color: blue;
}
</style>

親コンポーネントの定義が優先される。

slotにデフォルトの値を設定する。

likeHeader.vue
<slot>デフォルト</slot>

スロットタグの中に、デフォルトで表示したい値を設定する。

App.vue
<template>
  <div>
    <likeHeader> </likeHeader>
  </div>

</template>

親コンポーネントのカスタムタグに値を入れなかった場合は、デフォルトの値が表示される。

095becee7a6a6650a6332497b8b7f37b.png
逆に、カスタムタグの間に値を入れた場合は、デフォルトの値は表示されない。

likeHeader.vue
<slot>デフォルト</slot>

スロットタグの中に、デフォルトで表示したい値を設定する。

App.vue
<template>
  <div>
    <likeHeader>デフォルトじゃない</likeHeader>
  </div>

</template>

60a9553803f6487980a39de29774a3dc.png

名前付きslotで表示を分ける。

App.vue
<template>
  <div>
    <likeHeader>
      <template v-slot:title>タイトル</template>
      <template v-slot:content>コンテンツ</template>
    </likeHeader>
  </div>
</template>

<script>
import likeHeader from "./components/likeHeader.vue";

export default {
  components: {
    likeHeader,
  },
};
</script>
likeHeader.vue
<template>
  <div>
    <slot name="title"></slot>
    <slot name="content"></slot>
  </div>
</template>

親コンポーネントのカスタムタグ内にtemplateタグを設定し、v-slotディレクティブを設定し、任意の引数(title, content)を与える。
子コンポーネントで、slotタグに指定した任意の引数と一致する値(title, content)をname属性に与える。

デフォルトslot

v-slotディレクティブを指定したtemplateタブで囲われいない部分は、全て子テンプレートのデフォルトslot(name属性が与えられていないslot)に集約されて表示される。

App.vue
<template>
  <div>
    <likeHeader>
      <p>1</p>
      <template v-slot:title>タイトル</template>
      <p>2</p>
      <template v-slot:content>コンテンツ</template>
      <p>3</p>
    </likeHeader>
  </div>
</template>

<script>
import likeHeader from "./components/likeHeader.vue";

export default {
  components: {
    likeHeader,
  },
};
</script>
likeHeader.vue
<template>
  <div>
    <slot name="title"></slot>
    <slot></slot>
    <slot name="content"></slot>
  </div>
</template>

37fbad25f76dcb3bbdf61010be6483a4.png

この挙動は、親コンポーネント側で、templateタグに囲まれていいない部分を、新たにtemplateタグに集めて、そのtemplateタグにv-slot:default というディレクティブを与えている。
そして、子コンポーネントのデフォルトslotにname="default"を与えている。つまり下記のような処理をvueが自動で行っている。

App.vue
<template>
  <div>
    <likeHeader>
      <template v-slot:default>
        <p>1</p>
        <p>2</p>
        <p>3</p>
      </template>
      <template v-slot:title>タイトル</template>
      <template v-slot:content>コンテンツ</template>
    </likeHeader>
  </div>
</template>

<script>
import likeHeader from "./components/likeHeader.vue";

export default {
  components: {
    likeHeader,
  },
};
</script>
likeHeader.vue
<template>
  <div>
    <slot name="title"></slot>
    <slot name="default"></slot>
    <slot name="content"></slot>
  </div>
</template>

なお、soltに送る際は、templateタグでないとエラーとなる。(divタグとかではダメ)

slotを用いて子コンポーネントから親コンポーネントにデーターを渡す。

slotにカスタム属性をバインドすることにより、親子コンポーネントのv-slotの仮引数に格納することができる。!

IMG_BEDFBD4E6FC6-1.jpeg

c31e9f693e229720c3f3f1cee9507b3b.png

なお、v-slot:は # に置き換えることができる。

1
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
1
0