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

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

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

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

### コンパイルスコープ
* データをどこに置くべきかの説明ですね。

### 単一スロット

* App.vue

``` html

<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

``` html
<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>
```

* 少し味付けしてみます。

```html

<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

``` html
<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

``` html
<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

``` html

<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>
```

* 分割代入は、いろいろなところで、式を簡略化させるのに役立ちますね。


###動的コンポーネント

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

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

* その他編は、コンポーネントの理解を深めてからで良さそうな内容なので、後回しになる思います。
* 状態管理などが気になるので、そちらに行くと思います。(笑)