[Vue] 컴포넌트 - Emit

youngseo·2022년 5월 2일
0
post-thumbnail

한 번에 끝내는 프론트엔드 개발 초격차 패키지 Online를 들으며 정리한 내용입니다.

컴포넌트 - Emit

1. 이벤트 상속

App.vue

<template>
  <MyBtn @click="log">
    Banana
  </MyBtn>
</template>
<script>
import MyBtn from '~/components/MyBtn'

export default {
  components: {
    MyBtn
  },
  methods: {
    log() {
      console.log('Click!!')
    }
  }
}
</script>

MyBtn.vue

<template>
  <div class="btn">
    <slot></slot>
  </div>
</template>
<script>
export default {
}
</script>
<style scoped>
  .btn {
    display: inline-block;
    margin: 4px;
    padding: 6px 12px;
    border-radius: 4px;
    background-color: gray;
    color: white;
    cursor: pointer;
  }
</style>

MyBtn라는 컴포넌트를 클릭하면 log라는 함수가 실행될 수 있는 구조입니다. 하지만 이벤트는 화면에 있는 특정한 엘리먼트에 연결되어 있어야지만 동작을 합니다.

현재 자식 컴포넌트의 최상위 요소가 1개이며 따로 inheritAttrs:false가 작성되어 있지 않기에 속성 상속을 통해 이벤트는 잘 연결이 되고 실행될 수 있게 됩니다.

그렇다면 inheritAttrs:false옵션을 사용해야하거나, 자식 컴포넌트의 최상위 요소가 2개이상인 경우에는 어떻게 해야할까요?

이러한 경우 해당하는 요소에 이벤트를 직접적으로 연결해줄 수 있습니다.

2. Emit

자식 컴포넌트의 최상위 요소가 2개인 경우를 가정해보도록 하겠습니다.

<template>
  <div class="btn">
    <slot></slot>
  </div>
  <h1></h1>
</template>

1. emits 옵션에 이벤트 명시

아래와 같이 자식 컴포넌트의 script부분에 emits이라는 옵션을 추가해 사용할 이벤트를 정의해줍니다.

<script>
export default {
  emits: [
    'click'
  ]
}
</script>

2. 이벤트가 연결될 최상위 컴포넌트를 정의

최상위 컴포넌트 중 h1에 적용을 해보도록 하겠습니다.

아래와 같이 @click이라는 이벤트를 emits이라는 옵션을 통해 부모요소에 정의된 내용으로 가지고 와 명시를 한 후 이 명시된 내용을 $emit이라는 하나의 메소드의 첫번째 매개변수로 정의를 해줍니다.
MyBtn.vue

<template>
  <div class="btn">
  <slot></slot>
  <h1 @click="$emit('click')">
    ABC
  </h1>
</template>

이렇게 특정한 이벤트를 상속받아 emits라는 옵션에 연결을 해, $emit이라는 메소드를 통해 실행할 수 있습니다.

3. 심화 - 이벤트 이름 변경

이 클릭이라는 이벤트는 MyBtn이라는 컴포넌트의 emits이라는 부분으로 넘어가 내부에서 사용되기 때문에 굳이 click이라는 이름을 부여하지 않아도 괜찮습니다. 컴포넌트에 연결하는 이벤트는 실제로 쓸 수 있는 그 이벤트의 이름이 꼭 아니어도 상관 없습니다.

대신 정확하게 emits라는 옵션으로 받아서 그것이 어디에서 어떻게 사용이 되는지를 명시해줘야합니다.
App.vue

<template>
  <MyBtn @heropy="log"> //heropy로 수정
    Banana
  </MyBtn>
</template>

MyBtn.vue

<template>
  <div class="btn">
    <slot></slot>
  </div>
  <h1 @click="$emit('heropy')"></h1> //heropy로 수정
</template>
<script>
export default {
  emits: [
    'heropy' //heropy로 수정
  ] 
}
</script>

4. 심화 - 이벤트 객체 활용

이번에는 이벤트가 실제로 동작했을 때 이벤트 객체를 활용할 수 있는 부분에 대해서 배워보도록 하겠습니다.

App.vue

//App.vue
  methods: {
    log(event) {
      console.log('Click!!'),
      console.log(event)
    }

MyBtn.vue

  <h1 @click="$emit('click', $event )">//두번째 매개변수에 그 이벤트가 실행될 때의 데이터를 넘겨줄 수 있습니다.(이벤트라는 객체전달)

h1태그를 두번 클릭하면 'click!' 다음으로 두번째 매개변수로 들어간 mouseeven라는 객체가 출력되는 것을 확인할 수 있습니다.

4. 심화 - v-model

input요소를 만들어 v-model이라는 양방향데이터바인딩으로 msg라는 데이터를 한번 연결해보도록 하겠습니다.

<template>
  <div class="btn">
    <slot></slot>
  </div>
  <h1 @click="$emit('click', $event )">
    ABC
  </h1>
  <input
    type="text"
    v-model="msg" />
</template>
<script>
export default {
  emits: [
    'click'
  ],
  data() {
    return {
      msg: '' //data라는 옵션을 만들어 msg라는 데이터를 빈 문자열로 정의
    }
  }
}
</script>

화면의 input박스에 데이터를 입력할 때마다 실시간으로 msg라는 데이터를 갱신하게 되며 양방향데이터바인딩이기 때문에 변경된 msg데이터가 input요소에도 영향을 주고, input요소의 수정된 내용이 다시 msg에 영향을 줄 수 있는 구조가 만들어졌습니다.

5. 심화 - watch

sciprt에 watch라는 옵션을 추가해 msg라는 데이터가 변경될 때마다 app.vue에서 그 내용을 확인할 수 있도록 코드를 작성해보도록 하겠습니다.

MyBtn.vue

export default {
  emits: [
    'click',
    'changeMsg'   // 2) emits옵션에 명시
  ],
  watch: {
    msg(){
      this.$emit('changeMsg', this.msg) //1)msg를 감시하며 msg의 내용이 변경될 때마다 카멜케이스로 작성된 changeMsg라는 이벤트를 실행합니다.
    }
  }

App.vue

<template>
  <MyBtn @click="log" @change-msg="logMsg"> 3)✔️ html의 속성을 작성할때는 카멜케이스를 사용하지 않기 때문에 대쉬캐이스로 수정해줘야합니다.
    Banana
  </MyBtn>
</template>
<script>
import MyBtn from '~/components/MyBtn'

export default {
  components: {
    MyBtn
  },
  methods: {
    log(event) {
      console.log('Click!!'),
      console.log(event)
    },
    logMsg(msg){
      console.log(msg) 4) logMsg를 명시
    }
  }
}
</script>

0개의 댓글