본 포스팅은 Vuetify를 활용한 Alert Component 제작기를 담고 있습니다.

 


 

배경 : 사용자가 정보를 등록하거나 업데이트할 때마다 띄워줄 Alert Component를 제작

1. 다양한 페이지에서 쓰일 수 있기에 매번 import하는 것보다 Global import가 마땅하다 판단

1-1. @/components/Module/AlertDialog.vue 해당 경로에 적당한 Component를 제작

- trigger를 통해서 v-model:dialog를 열어주고, setTimeout으로 닫아주도록 제작(문서 내 2-3 코드 확인)

1-2. main.js에 global import(전역 등록)

// main.js
Vue.component("AlertDialog", () => import("@/components/Module/AlertDialog.vue"))

 

 

 


 

배경
: Global로 등록했으나, router가 변경되는 상황에서는 setTimeout 끝까지 기다리지 않고 dialog도 함께 없으질 것으로 판단.
: Parent Component에서 dialog를 toggle해주는 methods를 매번 등록해야하는 불편함.

So, 어디에서든 켜져있는 Parent component와 어디에서든 접근할 수 있는 데이터가 필요.
- 어디에서든 켜져있는 Parent component = Navigation Component
- 어디에서든 접근할 수 있는 데이터 = Vuex(store)

2. Vuex(store) + Navigation을 활용한 컴포넌트 제작

2-1. Vuex(store > index.js)

차후 사용처(2-4)에서 "dispatch"를 통해

store의 actions를 호출하면,

actions에서 mutation를 호출하고,

mutations에서 state의 데이터를 변이시킨다.

export default new Vuex.Store({
  state: {
    alertDialogToggle: false,
    alertDialogInfo: null,
   },
  mutations: {
    openAlertDialog(state, payload) {
      state.alertDialogInfo = payload
      state.alertDialogToggle = true
    },
    closeAlertDialog(state) {
      state.alertDialogInfo = null
      state.alertDialogToggle = false
    },
  },
  actions: {
    // Alert Dialog
    openAlertDialog({ commit }, alertDialogInfo) {
      commit("openAlertDialog", alertDialogInfo)
    },
    closeAlertDialog({ commit }) {
      commit("closeAlertDialog")
    },
  },

 

2-2. Navigation (components > NavBar.vue ) *제작하는 웹페이지 어디에서든 열려있는 네비게이션 컴포넌트

Tip. alert-dialog에 v-if를 넣어서 props undefied를 방지함과 동시에, Toggle이 닫히면 component가 destroy될 수 있도록 한다.

<template>
    <alert-dialog
      v-if="alertDialogToggle" // Tip
      :dialog="alertDialogToggle"
      :timeout="alertDialogInfo.timeout"
      :emoji="alertDialogInfo.emoji"
      :title="alertDialogInfo.title"
      :firstLineText="alertDialogInfo.firstLineText"
      :secondLineText="alertDialogInfo.secondLineText"
      :thirdLineText="alertDialogInfo.thirdLineText"
    ></alert-dialog>
</template>

<script>
import { mapState } from "vuex"
export default {
  components: {
    AlertDialog,
  },
  computed: {
    ...mapState(["alertDialogToggle", "alertDialogInfo"]),
    //   alertDialogToggle() {
    //     return this.$store.state.alertDialogToggle
    //   },
    //   alertDialogInfo() {
    //     return this.$store.state.alertDialogInfo
    //   },
  },
}
</script>

 

2-3. Alert Dialog Component (component > module > AlertDialog.vue)

<template>
  <v-dialog v-model="dialog" max-width="250">
    <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: 1000,
    },

    emoji: String,
    title: String,
    firstLineText: String,
    secondLineText: String,
    thirdLineText: String,
  },
  mounted() {
    setTimeout(() => {
      this.$store.dispatch("closeAlertDialog")
    }, this.timeout)
  },
  // destroyed() {
  //   console.log("destoyed")
  // },
}
</script>

<style></style>

 

2-4. 사용처 사용방법과 결과 화면

다른 로직을 완수한 후 openAlert() methods를 호출하여

데이터를 셋팅하고 dispatch를 통해 store의 내용을 변경한다.

곧바로 $this.router.push로 페이지를 이동시켜도

destoyed되지 않고 정상 작동하는 모습을 볼 수 있다.

  methods: {
    openAlert() {
      let alertDialogInfo = {
        // timeout: 5000,
        emoji: "🙏🏻",
        title: "카페가 성공적으로 등록되었어요!",
        firstLineText: "도움에 감사드립니다",
        secondLineText: "by.ccaaffee",
        // thirdLineText: "셋째줄",
      }
      this.$store.dispatch("openAlertDialog", alertDialogInfo)
    },
 }

 

 

 

추가 팁 

Parent에서 child로 Number 타입의 "params" props를 넘기고 싶다면

// Child
props: {
  params: {
     type: Number
  }
}


// Parent
<parent :params="5000" /> 
// params="5000" 와 같이 넘기면 String 타입으로 에러 발생

 

 

 

 

 


 

 

 

 

2편 예고 : Vue Global Alert Component 제작기(2)

: 부모에게 대드는 자식을 잡아보자.

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"

 

 

*본 포스팅의 모든 코드 블럭에는 주제와 무관한 내용의 코드를 생략하였습니다.

 


잘하셨습니다, OHMH(애매)

2021.02.20.

 

 

 

 

 

 

 

 

 

+ Recent posts