본문 바로가기
Framework/vue_Architecture

Custom Event (vue.js)

by cariño 2023. 1. 6.
728x90
반응형

props로 보낸 값은 값 읽기전용 속성이다. 그렇기 때문에 해당 값은 재정의 할 수 없다.

이럴 경우는 자식 컴포넌트에서 값을 변경하고 싶다면, 이벤트를 통해서 부모에게 전달할 수 있다. 

 

$emit

자식 컴포넌트에서 값을 변화하려면 이벤트를 부모에게 전달

//DetailView.vue
<template>
  <div class="wrapper">
    <div class="container">
      <h2>Modal Page</h2>
      <button @click="closeDetail">close</button>
    </div>
  </div>
</template>

<script>
export default {
  name:'detail-view',
  props: {
    displayShow: Boolean
  },
  methods:{
    closeDetail() {
      this.$emit("closeDetail")
    }
  }
}
</script>

위 로직은 자식 모달창 컴포넌트이다. 여기서 작동되야 하는 부분은 모달창을 닫는 close 버튼이다. 

displayShow가 부모쪽에서 boolean값을 통해 true일 경우 open되었다. 

그렇다면, props로 displayShow를 받아 자식 컴포넌트에서 false로 만들어 주면 되지 않을까? 생각하지만 당연히 될 수 없다. 위에 써 놓은것과 같이 props는 읽기 속성이고 값의 변경이 불가능하다. 

 

 

$emit('보낼메시지') 함수를 이용해서 해당 이벤트를 $emit을 통해 부모에게 전달한다. 

methods에 따로 보내도 되지만 인라인으로 간단하게 보낼 수도 있다. 

<button @click="$emit('closeDetail')">close</button> 

 

 

//App.vue
<template>
  <DetailView v-show="displayShow" @closeDetail="controlModal"/>
  <button @click="controlModal">click modal</button>
</template>

<script>
import DetailView from "./components/architecture/DetailView.vue";
export default {
  name: "App",
  components: { DetailView },
  data() {
    return {
      displayShow: false,
    };
  },
  methods: {
    controlModal(){
      this.displayShow = !this.displayShow
    },
    close(){
      this.displayShow = false
    }
  }
};
</script>

 

이제 이벤트를 전달 받을 때  @자식이 보낸 이름 = "변경할 내용" 을 사용한다.

변경할 내용의 이름은 받은 이름과 동일하게 할 수 있지만 부모 컴포넌트에서만 사용할 이름으로 변경해도 무관하다.

처음에는 close로 받아서 methos에 추가했지만,  controlModal()함수와 같은 내용이기에 closeDetail의 value로 controlModal로 변경하였다.

 

 

 

$emit 

 

자식 컴포넌트내에 input 값을 부모가 받을 수 있게 하기

input에 입력된 데이터 값을 두번째 인자에 넣은 후 전송할 수 있다.

인자값은 추가가 될 수 있다. 

sendData() {
   this.$emit('sendData', this.username);
   // 전송할 메시지, 전송할 데이터
},

 

<template>
  <div>
      <input type="text" v-model="userName">
      <button @click="sendData">전송</button>
    </div>
  </div>
</template>

<script>
export default {
  name:'detail-view',
  data(){
    return{
      userName: ''
    }
  },
  methods:{
    sendData() {
      this.$emit('sendData', this.username);
    },
  }
}
</script>

 

<template>
  <DetailView @sendData="showData"/>
</template>

<script>
import DetailView from "./components/architecture/DetailView.vue";
export default {
  name: "App",
  components: { DetailView },
  methods: {
    showData(data){
      console.log('data:', data)
    }
  }
};
</script>
728x90

'Framework > vue_Architecture' 카테고리의 다른 글

http통신 연습(vue)  (0) 2023.01.09
Components_provide, inject, Dynamic component(2)  (0) 2023.01.06
Components(1)  (0) 2023.01.06
Vue Router - Route, Router 차이  (0) 2023.01.05
Composition API: ref() vs reactive()  (0) 2023.01.02

댓글