2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vue.jsのコンポーネント間でデータを渡す方法(slotについて)

Last updated at Posted at 2022-07-07

はじめに

私自身がslotについて調べてわかったことについてまとめました。

slotって?

slotは親コンポーネントから子コンポーネントにデータを渡す手段です。
slotを利用して子コンポーネントのデータを取り出して親コンポーネントで利用することはできません。(実はできますが、きっとやらないでしょう)
子コンポーネントからデータを取り出したい場合はemit等を利用しましょう。

slotの基本

以下は仮に「my-hello」コンポーネントがあると想定し、データの渡し方と受け取ったデータの使い方を紹介します。

親コンポーネント側の記述方法(データの渡し方)

<!-- コンポーネントタグで渡したいデータを挟む -->
<my-hello>vue.js</my-hello>

コンポーネントタグで渡したいデータを囲むことでコンポーネントにデータを渡すことができます。

子コンポーネント側の記述方法(受け取ったデータの使い方)

const MyHello = {
template: `
<!-- 受け取ったデータがslotタグが囲んだ中に表示される -->
<div>こんにちは、<slot>xxx</slot>さん!</div>
  `,
}

slotタグで囲んだところに受け取ったデータが表示されます。
上記の例では以下のhtmlが生成されます。

<div>こんにちは、vue.jsさん!</div>

データはマスタッシュ構文等でリアクティブに渡すことも可能です。
データは文字列だけでなく、データを渡す側でhtmlの構文に則って記述することでレイアウトも指定することが可能です。

v-slotを利用して複数のデータを渡す

親コンポーネント側の記述方法(データの渡し方)

<my-hello>
  <p>ゲスト0</p>
  <template v-slot:guest1>ゲスト1</template>
  <template v-slot:guest2>ゲスト2</template>
  <template v-slot:default><p>ゲスト3</p></template>
  <p>ゲスト4</p>
</my-hello>

子コンポーネント側の記述方法(受け取ったデータの使い方)

const MyHello = {
  template: `
<div>こんにちは、<slot name="guest1">xxx</slot>さん!</div>
<div>こんにちは、<slot name="guest2">xxx</slot>さん!</div>
<div><slot>xxx</slot></div>
  `,
}

<template v-slot:guest1>で指定した内容が<slot name="guest1">に表示され、
<template v-slot:guest2>で指定した内容が<slot name="guest2">に表示され、
v-slotで指定しなかった内容や<template v-slot:default>で指定した内容、は全て<slot>に表示されます。
上記の例では以下のhtmlが生成されます。

<div>こんにちは、<slot name="guest1">ゲスト1</slot>さん!</div>
<div>こんにちは、<slot name="guest2">ゲスト2</slot>さん!</div>
<div>
  <p>ゲスト0</p>
  <p>ゲスト3</p>
  <p>ゲスト4</p>
</div>

v-slotによりslotタグのname属性の値を指定し、紐づけることができ、複数の値を指定することができます。
v-bindならば「:」やv-onならば「@」のようにv-slotならば「#」に省略することもできます。

slot内で子コンポーネントのデータにアクセスする方法

親コンポーネント側の記述方法(データの渡し方)

<my-hello>
  <template v-slot:default="slotProp">
    <div>
      <p>こんにちは、{{slotProp.guest.name}}さん!</p>
      <p>{{slotProp.guest.age}}歳ですね。</p>
    </div>
  </template>
</my-hello>

親コンポーネントでv-slot:default="slotProp"と記述することで子コンポーネントのプロパティにアクセスできるようになります。

子コンポーネント側の記述方法(受け取ったデータの使い方)

const MyHello = {
  data() {
    return {
      guest: {
        name: 'ゲスト1',
        age: 28,
      },
    };
  },
  template: `
<slot v-bind:guest="guest">xxx</slot>
  `,
}

コンポーネント側でv-bind:guest="guest"と記述することでguestプロパティとdataのguestを紐づけています。
これによって親コンポーネントで、slotProp.guestと記述することでdataのguestにアクセスできるようになります。
上記の例では以下のhtmlが生成されます。

<div>
  <p>こんにちは、ゲスト1さん!</p>
  <p>28歳ですね。</p>
</div>

この機能はデータは同じだけれどもテンプレートを要所で変更したいケースで使いやすそうです。

番外編:力ずくでデータを取り出す方法

上記の例を改造して子コンポーネントのdataのguestを取り出してみます。

親コンポーネント側の記述方法(データの渡し方 受け取ったデータの使い方)

const = MyParent{
  data(){
    return {
      guestName: null,
    };
  },
  template: `
<div>
  <my-hello>
    <template v-slot:default="slotProp">
      <!-- データを受け取る -->
      <div style='display:none;'>{{ guestName = slotProp.guest.name }}</div>
    </template>
  </my-hello>
  {{ guestName }}
</div>
  `,
  components: {
    'my-hello': MyHello,
  },
}

子コンポーネント側の記述方法(受け取ったデータの使い方 データの渡し方)

const MyHello = {
  data() {
    return {
      guest: {
        name: 'ゲスト1',
        age: 28,
      },
    };
  },
  template: `
<slot v-bind:guest="guest">xxx</slot>
  `,
}

上記の例では親コンポーネントで<template v-slot:default="slotProp">の中でのみguestデータにアクセスできるのでその中で親コンポーネントのdataのguestNameにデータを代入して取り出しています。こんな使い方をするのは是非やめてください。

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?