前置き
slot応用編に入れる予定だった
総合まとめが入り切らず
上級編にしました!
slot基礎編、応用編どちらも
クリアした方向けです。
基礎編はこちら。
こんな使い方もできる!
今まで紹介してきたslotは
子でslot、親にテキストでしたが、
今回はちょっと違うパターンです!
こういったモーダルウィンドウ
いくつも作りたい場合。
テキストの外側の装飾、
いちいち書くのは面倒ですね…!
そして中身も1つ1つ
別のコンポーネントを作りたい、
そんな時の使い方です。
アイコンはiconmonstrさんでお借りしました。
closeで検索、
svgコードを貼り付けて使用しております。
https://iconmonstr.com/
step
1まずは外側のコンポーネントを作成
(背景の白い部分と閉じるボタン)
中身をslotで自由にデータを表示させます。
slotの使い方が分かれば良いので、
スタイリングは省きます。
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<template> <div class="modal-wrap"> <button class="button" @click="$emit('close')"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"/></svg> </button> <slot /> </div> </template> <script> </script> <style lang="scss" scoped> </style> |
step
2中身のコンポーネントを作成
) components
1 2 3 4 5 6 7 8 9 10 11 |
<template> <div class="modal-text"> <p>Hello Nuxt.js!</p> </div> </template> <script> </script> <style lang="scss" scoped> </style> |
step
3親ページでModalTextをModalWrapで囲む
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<template> <div class="page"> <div v-if="active" class="modal"> // グレーの背景 <div class="background" /> // ModalWrapのslot部分がModalTextに置き換わる <ModalWrap @close="active = false"> <ModalText /> </ModalWrap> </div> </div> </template> <script lang="ts"> import ModalWrap from '~/components/ModalWrap.vue' import ModalText from '~/components/ModalText.vue' export default { components: { ModalWrap, ModalText, }, data () { return { active: false, } }, }) </script> <style lang="scss" scoped> </style> |
これだけです!
とっても便利ですよね😄
Vue.jsバージョン 2.6.0での使い方
追加された新機能、 v-slot:を#で省略して書いてます。
使い方自体は一緒です!
省略できるよ、いえーいってだけ。
v-slot: titleなら #title になります。
) components
1 2 3 4 5 6 7 8 |
<h2 class="item_title"> <slot name="title"> Title // ここはslotで置き換えられるため消える </slot> <span> <slot name="catchCopy">Catch Copy</slot> </span> </h2> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<ItemTitle> <template #title> // v-slot:を#で省略(v-slot:title) {{ hero.title }} </template> <template #catchCopy> // v-slot:を#で省略(v-slot:catchCopy) {{ hero.catchCopy }} </template> </ItemTitle> <script> import ItemTitle from '../components/ItemTitle.vue'; export default { data () { return { hero: { title: "PageTitle", catchCopy: [ "catchCopy1", "catchCopy2" ] }, } }, components: { ItemTitle: ItemTitle, } } </script> |
結果
1 2 3 4 |
<h2 class="item_title"> PageTitle // hero.titleが呼び出される <span> [ "catchCopy1", "catchCopy2" ]</span> // hero.catchCopyが呼び出される </h2> |
まとめ
色々やってきましたが、
超シンプルにまとめます。
slotで改行しなくて良いのですが、
slot部分を強調するため改行しています。
slot1つ
子にslot、親にテキスト
) components
1 2 3 4 5 |
<template> <h1> <slotここに書いたものは無視される</slot> </h1> </template> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<template> <div class="page"> <Component> slotを学ぼう! </Component> </div> </template> <script> import Component from '~/components/Component.vue' export default { components: { Component, }, } </script> |
slot2つ以上
デフォルト1つと、
他にslot nameつける
親でtemplateでslotを置き換える
template v-slot:name
もしくは
template #name
) components
1 2 3 4 5 6 7 8 9 10 11 |
<template> <div> <slot /> <h1> <slot name="title" /> </h1> <h2> <slot name="subTitle" /> </h2> </div> </template> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<template> <div class="page"> <Component> <img src="~"> <template #title> slotを学ぼう! </template> <template #subTitle> slotを使おう! </template> </Component> </div> </template> <script> import Component from '~/components/Component.vue' export default { components: { Component, }, } </script> |
子の内容が反映されてしまうケース
どちらのslotにもslot nameつけたのに
v-slotしないと子の内容が直接反映されます。
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<template> <div class="component"> <h1> <slot name="title">Hello Nuxt.js!</slot> </h1> <h2> <slot name="subTitle">slotを学ぼう!</slot> </h2> <p> <slot /> </p> </div> </template> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<template> <div class="page"> <Component> <template #title> ハロー! </template> やっほー! </Component> </div> </template> <script> import Component from '~/components/Component.vue' export default { components: { Component, }, } </script> |
結果
1 2 3 4 |
<div class="component"> ハロー! slotを学ぼう! </div> |
slotは沢山記事にしましたが、
まとめると超簡単ですよね🤗