Vue에서는 사용자 지정 이벤트를 사용하여 서로 다른 컴포넌트 간에 통신할 수 있습니다.
템플릿에서 사용자 지정 이벤트를 내보내려면 $emit메서드를 사용하여 이벤트 이름과 이벤트에 포함할 페이로드를 전달할 수 있습니다.
아래는 $emit 메서드를 이용하여 자식 컴포넌트가 부모 컴포넌트에게 데이터를 전달하거나 데이터를 변경하도록 요청하는 방법들입니다.
# 템플릿에서 이벤트를 요청
$emit 메서드를 사용하여 이벤트 이름과 이벤트에 포함할 페이로드를 전달할 수 있습니다.
// 자식 컴포넌트의 템플릿에서 사용자 지정 이벤트를 요청
<template>
<button @click="$emit('my-custom-event', { message: 'Hello, world!' })">
Click me
</button>
</template>
# 스크립트에서 이벤트를 요청
this.$emit 메서드를 사용하여 컴포넌트의 스크립트 태그에서 사용자 지정 이벤트를 내보낼 수도 있습니다 .
// 자식 컴포넌트의 스크립트 태그에서 사용자 지정 이벤트를 요청
export default {
methods: {
handleClick() {
this.$emit('my-custom-event', { message: 'Hello, world!' });
}
}
}
# v-on 지시문으로 이벤트를 수신
자식 컴포넌트에서 보낸 사용자 지정 이벤트를 수신하려면 v-on지시문을 사용하고 수신하려는 이벤트의 이름을 작성하여 바인딩 할 수 있습니다.
// 부모 요소는 v-on을 사용해 이벤트를 수신
<template>
<child-component v-on:my-custom-event="handleCustomEvent"></child-component>
</template>
<script>
export default {
methods: {
handleCustomEvent(payload) {
console.log(payload.message); // "Hello, world!"
}
}
}
</script>
# @로 이벤트를 수신
v-on:은 @로 줄여 쓸 수 있습니다
// v-on은 아래와 같이 @를 이용해 사용할 수 있음
<template>
<child-component @my-custom-event="handleCustomEvent"></child-component>
</template>
<script>
export default {
methods: {
handleCustomEvent(payload) {
console.log(payload.message); // "Hello, world!"
}
}
}
</script>
# Payload란?
페이로드는 이벤트와 함께 전달하는 데이터이며, 모든 유형의 데이터를 사용할 수 있습니다.
예를 들어 아래 예는 $emit을 이용하여 자식 컴포넌트에서 부모 컴포넌트로 메시지를 보내는 데 사용하고 있습니다.
<template>
<button @click="$emit('send-message', 'Hello, world!')">Click me</button>
</template>
위 예에서 자식 컴포넌트는 라는 사용자 지정 이벤트 send-message를 보내고, 데이터(Hello, world!라는 문자열)을 페이로드로 전달합니다.
부모 컴포넌트는 이 이벤트를 수신하고 methods를 사용하여 페이로드에 액세스할 수 있습니다 .
<template>
<child-component v-on:send-message="handleMessage"></child-component>
</template>
<script>
export default {
methods: {
handleMessage(message) {
console.log(message); // "Hello, world!"
}
}
}
</script>
페이로드는 여러 데이터를 포함하는 객체일 수도 있습니다.
// 자식 컴포넌트
<template>
<button @click="$emit('send-message', { message: 'Hello, world!', sender: 'Child component' })">Click me</button>
</template>
이와 같은 경우 페이로드는 message및 sender라는 두 가지 속성을 포함하는 객체입니다.
부모 구성 요소는 점(.) 표기법을 사용하여 이러한 속성에 액세스할 수 있습니다.
// 부모 컴포넌트
<template>
<child-component v-on:send-message="handleMessage"></child-component>
</template>
<script>
export default {
methods: {
handleMessage(payload) {
console.log(payload.message); // "Hello, world!"
console.log(payload.sender); // "Child component"
}
}
}
</script>
$emit를 사용하여 사용자 지정 이벤트를 내보낼 때 문자열, 숫자, 개체, 배열 등 모든 유형의 데이터를 페이로드로 전달할 수 있습니다 .
# emit을 사용할 때 자주 볼 수 있는 경고 해결하기
경고문
[Vue warn]: Extraneous non-emits event listeners (item) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option.
해결 방법
요청을 하는 자식 요소의 스크립트에 emits 항목을 추가해 줍니다.
// 자식 요소의 스크립트에 emits 추가
export default {
emits: ['my-custom-event'],
methods: {
handleClick() {
this.$emit('my-custom-event', { message: 'Hello, world!' });
}
}
}
요청하는 이벤트가 여러개 일경우 아래와 같이 배열처럼 이벤트 이름을 작성해 줍니다.
// 요청하는 이벤트가 여러개일 경우 아래와 같이 각각의 이벤트를 배열처럼 작성
export default {
emits: ['my-custom-event1', 'my-custom-event2', 'my-custom-event3'],
methods: {
handleClick1() {
this.$emit('my-custom-event1', { message: 'Hello, HTML!' });
},
handleClick2() {
this.$emit('my-custom-event2', { message: 'Hello, CSS!' });
},
handleClick3() {
this.$emit('my-custom-event3', { message: 'Hello, JavaScript!' });
}
}
}
위 방법으로도 경고문이 해결이 되지 않는다면 이제는 사용되지 않는 emits가 부모 요소에 정의되어 있지는 않는지 확인해 봅시다.