Help us understand the problem. What is going on with this article?

初心者がVue.jsの公式ガイドを勉強するメモ コンポーネント編 第二部 スロット関係

More than 1 year has passed since last update.

コンポーネント編 第二部 スロット関係

https://jp.vuejs.org/v2/guide/components.html

スロットによるコンテンツ配信

コンパイルスコープ

  • データをどこに置くべきかの説明ですね。

単一スロット

  • App.vue
<template lang="pug">
  #app
    button(@click="toggle=!toggle") Toggle button
    div
      h1 Parent title
      child-component
        p(v-if="toggle") Parent content
        p(v-if="toggle") Parent content 2

</template>

<script>

import Vue from 'vue'

Vue.component('child-component', {
  template: `<div>
    <h1> Child Title</h1>
    <slot>
      slot content コンポーネントに子要素が無い場合に表示されます。
    </slot>
  </div>`
  })

export default {
  name: 'app',
  data () {
    return {
      toggle: true
    }
  },
  components: {
  }
}
</script>
  • コンポーネントの子要素が無い場合に使われるみたいです。
  • ちなみに、v-show では、子要素が消えないためslotは使われません。

名前付きスロット

  • App.vue
<template lang="pug">
  #app
    app-layout
      h1(slot="header") Header Title
      p main content.
      p main content 2.
      p(slot="footer") Footer

</template>

<script>

import Vue from 'vue'

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

export default {
  name: 'app',
  data () {
    return {
      toggle: true
    }
  },
  components: {
  }
}
</script>
  • 少し味付けしてみます。
<template lang="pug">
  #app
    app-layout
      h1(slot="header") Header Title
      p main content.
      p main content 2.
      p(slot="footer") Footer

</template>

<script>

import Vue from 'vue'

Vue.component('app-layout', {
  template: `<div class="container">
    <header class="header">
      <slot name="header"></slot>
      <h2 class="sub-title"> SubTitle</h2>
    </header>
    <main class="main">
      <slot></slot>
      <p>Main Content 3</p>
    </main>
    <footer class="footer">
      <slot name="footer"></slot>
      <small>  from 2017 to {{ format }} </small>
    </footer>
  </div>`,
    computed: {
      format () {
        const date = new Date();
        const year = date.getFullYear();
        return year
      }
    }
  })

export default {
  name: 'app',
  data () {
    return {
      toggle: true
    }
  },
  components: {
  },
  computed: {
  }
}
</script>
  • スロットに名前をつけて、指定したタグを呼び出していますね。
  • 名無しのslotは、default tag として、個別に呼び出さないものは、この場合mainタグが呼び出されるみたいです。
  • 前回は、子要素の有無でスイッチとしての機能をみましたが、今回は、tagの切り替えとして使っていますね。

スコープ付きスロット

  • App.vue
<template lang="pug">
  #app
    .parent
      child
        template(slot-scope="props")
          span hello from parent
          span {{ props.text }}

</template>

<script>

import Vue from 'vue'

Vue.component('child', {
  template: `<div class="child">
    <slot text="hello from child"></slot>
  </div>`
})

export default {
  name: 'app',
  data () {
    return {
      toggle: true
    }
  },
  components: {
  }
}
</script>
  • propsを引数にして、コンポーネント側のslotのテキストを引っ張ってきています。
  • 作成には、templateにslot-scope属性が必要です。(2.1.0 ~ 2.5.0)

  • App.vue

<template lang="pug">
  #app
    .parent
      my-awesome-list(:items="items")
         li(
          slot="itemSlot"
          slot-scope="props"
          class="my-fancy-item"
         )
          span {{ props.text }}

</template>

<script>

import Vue from 'vue'

Vue.component('my-awesome-list', {
  props: ["items"],
  template: `<ul>
    <slot name="itemSlot" :text="item.name" v-for="item in items"></slot>
  </ul>`
})

export default {
  name: 'app',
  data () {
    return {
      items: [
        { name: 'apple' },
        { name: 'banana' },
        { name: 'Natto' },
      ]
    }
  },
  components: {
  }
}
</script>

  • <template>制限がなくなった見たいです。

分割代入

  • App.vue
<template lang="pug">
  #app
    .parent
      my-awesome-list(:items="items")
         li(
          slot="itemSlot"
          slot-scope="{ text }"
          class="my-fancy-item"
         )
          span {{ text }}

</template>

<script>

import Vue from 'vue'

Vue.component('my-awesome-list', {
  props: ["items"],
  template: `<ul>
    <slot name="itemSlot" :text="item.name" v-for="item in items"></slot>
  </ul>`
})

export default {
  name: 'app',
  data () {
    return {
      items: [
        { name: 'apple' },
        { name: 'banana' },
        { name: 'Natto' },
      ]
    }
  },
  components: {
  }
}
</script>
  • 分割代入は、いろいろなところで、式を簡略化させるのに役立ちますね。

動的コンポーネント

  • 飛ばします。
  • 同じマウントポイントでの切り替え機能みたいです。

  • その他が残っていますが、スロット関係の大枠がほぼ把握できたので、ここで一旦終了します。

  • その他編は、コンポーネントの理解を深めてからで良さそうな内容なので、後回しになる思います。

  • 状態管理などが気になるので、そちらに行くと思います。(笑)

atoris
難しかったことが、簡単にできるようにする。 コードで少しづつ実現していきたい
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした