前置き
前回の続きです🌟
https://note.com/aliz/n/n47b0d98be524
1つのcomponentsで
複数のModalを表示させましょう✨
Step5: 中身をcomponents分けする
Modalの外側と内側で
componentsを切り分けていきましょう。
queryによって切り替えているpタグを
organismsに移動させます🎈🧸
propsを使わなくて済むので
本当にただ移動させるだけです、楽ちん♪
components/
--| organisms/
----| modals/
-----| ModalContainer.vue
--| templates/
----| modals/
-----| ModalRoute.vue
layouts/
--| default.vue
<template>
<div class="modal-container">
<!-- 切り替える中身 -->
<p
v-if="$route.query.modal === 'login'"
class="text"
>
{{ $route.query.modal }}
</p>
<p
v-if="$route.query.modal == 'register'"
class="text"
>
{{ $route.query.modal }}
</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'Modal',
})
</script>
<style lang="scss" scoped>
.modal-container {
.text {
font-size: 36px;
}
}
</style>
Step6: 中身をFormにする
ついでにformを作りましょう🌟
password入力のinputも作ると
inputをmoleculesで作る必要が出てくるので
一旦イメージだけできればOKです🧸🍯
<template>
<div class="modal-container">
<!-- 切り替える中身 -->
<form
class="form"
v-if="$route.query.modal === 'login'"
@submit.prevent
>
<label class="label">
<span class="label">
{{ $route.query.modal }}
</span>
<input
v-model="form.email"
:type="type"
placeholder="email"
>
</label>
<button
class="button"
type="submit"
@click="$emit('submit', form)"
>
{{ $route.query.modal }}
</button>
</form>
<form
class="form"
v-if="$route.query.modal === 'register'"
@submit.prevent
>
<label class="label">
<span class="label">
{{ $route.query.modal }}
</span>
<input
v-model="form.email"
:type="type"
placeholder="email"
>
</label>
<button
class="button"
type="submit"
@click="$emit('submit', form)"
>
{{ $route.query.modal }}
</button>
</form>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'Modal',
data () {
return {
form: {
email: '',
},
}
},
props: {
type: {
type: String,
default: 'text',
},
},
})
</script>
<style lang="scss" scoped>
.modal-container {
.form {
.label {
font-size: 24px;
.label {
display: block;
}
}
.button {
display: block;
}
}
}
</style>
【解説】
・@click="$emit('submit', form)"
inputに入力する値formを$emitで渡します。
<template>
<div
v-if="$route.query.modal"
class="modal-route"
>
<div
class="bg"
@click="$router.push('/')"
/>
<div class="modal-wrap">
<button
class="button"
@click="$router.push('/')"
>
<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>
<ModalContainer
@submit="submit"
/>
</div>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
name: 'Modal',
components: {
ModalContainer: () => import('@/components/organisms/modals/ModalContainer.vue'),
},
methods: {
submit (form) {
console.log(form) // eslint-disable-line
},
},
})
</script>
<style lang="scss" scoped>
.modal-route {
position: fixed;
top: 0;
width: 100%;
height: 100%;
.bg {
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-wrap {
border-radius: 8px;
background-color: #ffffff;
width: 50%;
height: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 30px;
.button {
border: none;
position: absolute;
top: 5%;
right: 2%;
}
}
}
</style>
【解説】
・@submit
$emitでつけたイベント名
・// eslint-disable-line
consoleなど特定の行に書かないと
ESLintでエラーになります。
https://qiita.com/nju33/items/2d0cfea4fffbfdbff87a
Step7: Formを分ける
今はformが2種類ですが
もし増えたら管理が面倒なので
分けてしまいましょう💡
え、1つのコンポーネントを
queryで切り替えるのが
メリットなんじゃないの?😲
分けたら意味なくない?😲
と思ったそこのアナタ❗️
安心してください🍑
componentタグを使えば良いのです✨
【ディレクトリ 】
modalsというファイルを作り
ModalContainerのform2つを
それぞれに分けましょう。
🌷before🌷
components/
--| organisms/
----| modals/
-----| ModalContainer.vue
--| templates/
----| modals/
-----| ModalRoute.vue
layouts/
--| default.vue
🌷after🌷
components/
--| templates/
----| modals/
-----| ModalRoute.vue
modals/
--| login.vue
--| register.vue
layouts/
--| default.vue
【modals/login.vue】
・formのregister部分を除きましょう🧹
・$emitのイベント名を分かりやすく
submitLoginに変更しましょう!
<template>
<div class="modal-container">
<!-- 切り替える中身 -->
<form
v-if="$route.query.modal === 'login'"
class="form"
@submit.prevent="$emit('submitLogin', form)"
>
<label class="label">
<span class="label">
{{ $route.query.modal }}
</span>
<input
v-model="form.email"
:type="type"
placeholder="email"
>
</label>
<button
class="button"
type="submit"
>
{{ $route.query.modal }}
</button>
</form>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
type: {
type: String,
default: 'text',
},
},
data () {
return {
form: {
email: '',
},
}
},
})
</script>
<style lang="scss" scoped>
.modal-container {
.form {
.label {
font-size: 24px;
.label {
display: block;
}
}
.button {
display: block;
}
}
}
</style>
【modals/register.vue】
変更部分はlogin.vueと同じです
<template>
<div class="modal-container">
<!-- 切り替える中身 -->
<form
v-if="$route.query.modal === 'register'"
class="form"
@submit.prevent="$emit('submitRegister', form)"
>
<label class="label">
<span class="label">
{{ $route.query.modal }}
</span>
<input
v-model="form.email"
:type="type"
placeholder="email"
>
</label>
<button
class="button"
type="submit"
>
{{ $route.query.modal }}
</button>
</form>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
type: {
type: String,
default: 'text',
},
},
data () {
return {
form: {
email: '',
},
}
},
})
</script>
<style lang="scss" scoped>
.modal-container {
.form {
.label {
font-size: 24px;
.label {
display: block;
}
}
.button {
display: block;
}
}
}
</style>
【components/organisms/modals/ModalRoute.vue】
<template>
<div
v-if="$route.query.modal"
class="modal-route"
>
<div
class="bg"
@click="$router.push('/')"
/>
<div class="modal-wrap">
<button
class="button"
@click="$router.push('/')"
>
<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>
<!-- <ModalContainer
@submit="submit"
/> -->
<component
:is="$route.query.modal"
@submitLogin="submit($event)"
@submitRegister="submit($event)"
/>
</div>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
name: 'Modal',
components: {
login: () => import('@/modals/login.vue'),
register: () => import('@/modals/register.vue'),
},
methods: {
submit (form) {
console.log(form) // eslint-disable-line
},
},
})
</script>
<style lang="scss" scoped>
.modal-route {
position: fixed;
top: 0;
width: 100%;
height: 100%;
.bg {
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-wrap {
border-radius: 8px;
background-color: #ffffff;
width: 50%;
height: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 30px;
.button {
border: none;
position: absolute;
top: 5%;
right: 2%;
}
}
}
</style>
【解説】
・component :is="$route.query.modal"
└:isでcomponentを呼び出します!
コンポーネントの登録が必要なので
中身をそれぞれimportしましょう📩
└それぞれを1つのコンポーネントとみなし
queryで切り替えましょう🍒
・@submitLogin="submit($event)"
└$emitのイベント名を変えたので
どちらも書きましょう✍️
└($event)は省略可能
お疲れ様でした🤗
完成です🎉💕
次回予告
【Nuxt.js】アプリ開発実践編:
Nuxt + Vuex + firebaseでログイン付きToDoリスト
こちらのTODOリストに
ログイン機能をつけていきます!✨
https://note.com/aliz/n/n8411db2c9a20
公開予定日は5/19(火)です🌟