コンポーネント編 第二部 スロット関係
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>
- 分割代入は、いろいろなところで、式を簡略化させるのに役立ちますね。
動的コンポーネント
- 飛ばします。
同じマウントポイントでの切り替え機能みたいです。
その他が残っていますが、スロット関係の大枠がほぼ把握できたので、ここで一旦終了します。
その他編は、コンポーネントの理解を深めてからで良さそうな内容なので、後回しになる思います。
状態管理などが気になるので、そちらに行くと思います。(笑)