Vuetify를 활용한 Alert Component 제작기 2편에서는 1편에서 잡지못한 에러를 잡아보겠습니다.
컴포넌트 기본 제작기를 보시려면 1편을 먼저 확인해주세요
ohmh.tistory.com/18
배경 : AlertDialog가 create되고, 우리가 설정한 timeout이 지나서 destroy되기 전에 dialog overlay를 클릭하면 발생하는 에러
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "dialog"
원인
: NavBar(parent)로부터 AlertDialog(child)로 넘겨받은 props 중 "dialog"가 있다.
: timeout이 지나기 전, dialog overlay를 클릭하면 이 "dialog" false로 만드는데,
: parent로부터 받은 props를 child에서 변경하면서 발생하는 에러
1. v-dialog props "persistant" 활용
Alert Dialog Component (component > module > AlertDialog.vue)
v-dialog에 persistent를 추가하여 overlay를 클릭해도 닫히지 않도록 조치한다.
<v-dialog v-model="dialog" persistent max-width="250">
2. Click Outside 활용
vuetify의 v-click-outside를 활용해보려고 했으나, 동일한 에러 발생.
onClickOutside로 store의 data를 mutation하기 이전에
default로 있는 click:outside가 먼저 작동.
따라서, @click:outside 활용
<template>
<v-dialog v-model="dialog" max-width="250" @click:outside="onClickOutside">
<!-- v-click-outside="onClickOutside" -->
// 생략
methods: {
onClickOutside() {
this.$store.dispatch("closeAlertDialog")
},
},
AlertDialog.vue 최종 코드
<template>
<v-dialog v-model="dialog" max-width="250" @click:outside="onClickOutside">
<!-- v-click-outside="onClickOutside" -->
<v-card>
<v-card-title class="justify-center mb-4" style="font-size: 2rem;">
<div>{{ emoji }}</div>
</v-card-title>
<v-card-subtitle class="text-center pb-2 font-weight-bold">
<div>{{ title }}</div>
</v-card-subtitle>
<v-card-text class="text-center">
<div v-if="firstLineText">{{ firstLineText }}</div>
<div v-if="secondLineText">{{ secondLineText }}</div>
<div v-if="thirdLineText">{{ thirdLineText }}</div>
</v-card-text>
</v-card>
</v-dialog>
</template>
<script>
export default {
// props: ["title", "firstLineText", "secondLineText", "ThirdLineText", "btnText", "dialog"],
props: {
dialog: Boolean,
timeout: {
type: Number,
default: 1500,
},
emoji: String,
title: String,
firstLineText: String,
secondLineText: String,
thirdLineText: String,
},
mounted() {
setTimeout(() => {
this.$store.dispatch("closeAlertDialog")
}, this.timeout)
},
methods: {
onClickOutside() {
this.$store.dispatch("closeAlertDialog")
},
},
// destroyed() {
// console.log("destoyed")
// },
}
</script>
<style></style>
이로써 바깥을 클릭해도 에러가 발생하지 않는 컴포넌트가 완성되었다.
잘 하셨습니다.
vuetifyjs.com/en/directives/click-outside/
잘하셨습니다, OHMH(애매)
2021.02.21.