自分用の備忘録的に…
まず、完成したのはこんなのです。よくあるTODOリストだけど、いちいち確認してくるモーダルのダイアログが追加時と完了設定時に入っています。(メンディ)
素直に実装するなら、TODO追加ボタンのonclickにダイアログの表示処理、ダイアログの「はい」ボタンのonclickにTODO追加の処理を書いていくことになると思います。でもそれだと同じダイアログを別の動作の中で使いまわすのも辛そうですし、後からコードを見た時に一連の動作が追いづらくなりますよね
そこでこんな実装にしてみました
<template>
<div>
<form @submit.prevent="doAdd">
<input type="text" v-model="title">
<button>add</button>
</form>
<ul>
<li v-for="(todo, i) in todos" :key="i">
<span class="todo-title" :class="{'done': todo.done}">{{todo.title}}</span>
<button @click="doMarkAsDone(i)" v-if="!todo.done">done</button>
</li>
</ul>
<div class="modal" v-if="isShowConfirmModal">
<div class="overlay"></div>
<div class="modal-container">
<div class="modal-body">
<p>マ?</p>
<button @click="$emit('answerdConfirm', true)">はい</button>
<button @click="$emit('answerdConfirm', false)">いいえ</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
title: '',
todos: [],
isShowConfirmModal: false,
};
},
methods: {
async doAdd() {
if (!await this.askConfirm()) return
this.todos.unshift({
title: this.title,
done: false,
})
this.title = ''
},
async doMarkAsDone(todoIndex) {
if (!await this.askConfirm()) return
this.todos = this.todos.map((todo, index) => ({
...todo,
done: index === todoIndex || todo.done,
}))
},
askConfirm() {
this.isShowConfirmModal = true
return new Promise(resolve =>
this.$once('answerdConfirm', confirmValue => {
this.isShowConfirmModal = false
resolve(confirmValue)
})
)
},
},
}
</script>
<style>
...
</style>
いろいろ荒いけど…
ポイントは、確認モーダル表示メソッド( askConfirm()
)でモーダルを開きつつ、 Promise
を返しているところです。
ユーザーが「はい」か「いいえ」のどちらかをクリックすると、 $emit
でイベントが発行され、それを $once
が受け取ると、先ほど返した Promise
が解決されます。
このようにすることで、TODO追加メソッド( doAdd()
)、TODO完了設定メソッド( doMarkAsDone
)のどちらでも、処理の一連の流れを分断することなく、ユーザーがダイアログで入力した値を受け取ることができます。
以上!