[Vue.js] emit 자세히 살펴보기(다양한 사용법, 예시)

토끼는 개발개발·2023년 9월 2일
3

Vue.js

목록 보기
13/19
post-thumbnail

이전 포스팅에서 propsemit에 대해 다뤘다.
이번 포스팅에서는 그 중 emit에 대해 좀 더 자세히 다뤄보겠다.


📌 emit 이벤트 내보내기

1. 이벤트 발신/수신

자식 컴포넌트에서 부모 컴포넌트로 데이터를 전달 또는 트리거의 목적으로 이벤트를 내보낼 수 있다. 이벤트는 컴포넌트의 emit 메서드를 통하여 발생시킬 수 있다.

컴포넌트의 <template> 블록 안에서 내장 함수 $emit()을 사용하여 직접 커스텀한 이벤트를 내보낼 수 있다.

예시를 살펴보자.

✨ 예제 1

<!-- PostCreate.vue 자식 컴포넌트 -->

<template>
  <div>
    <button @click="$emit('createPost'"></button> <!-- 자식에서 부모로 이벤트 'createPost'내보내기 -->
  </div>
</template>
<!-- TheView.vue 부모 컴포넌트 -->

<template>
  <div>
    <PostCreate @create-post="callFunction" ></PostCreate> <!-- 부모에서 이벤트 수신 -->
  </div>
</template>
<script>
  const callFunction = () => {
  	console.log('이벤트 수신');
  }
</scritp>

단계는 다음과 같다.

(1) 버튼 클릭 이벤트 발생 $emit('createPost') 실행
(2) 자식 -> 부모 'createPost' 이벤트 내보냄
(3) 부모에서 @create-post로 이벤트 수신하고 callFunction 함수 실행
(4) 콘솔창에 '이벤트 수신' 출력됨.


여기서 잠깐, 이상한 점을 발견할 수 있다.
자식에서 보낸 이벤트는 'createPost'로 카멜케이스였지만, 부모에서는 'create-post' 케밥케이스로 수신했다.

이게 가능한 것일까?
가능하다. 심지어 추천되는 방법이다.

💡 자식은 카멜케이스로 발신, 부모는 케밥케이스로 수신

자식에서 카멜케이스 형식으로 이벤트를 발신했지만, 부모에서 케밥케이스 표기로 리스너를 사용하여 이를 수신할 수 있다.

@v-on이다. v-on이벤트리스너는 항상 자동으로 소문자 변환을 하기때문에 'createPost'가 아닌 'createpost'로 변환된다. 이러한 변환 과정으로 인해 카멜케이스는 호출에 있어 문제를 발생시킬 수 있다.

따라서, 리스너 이벤트 이름은 케밥케이스로 작성하는 것이 좋다.




2. 이벤트 파라미터

이벤트와 함께 특정 값을 내보낼 수 있다.
$emit 함수 이벤트명에 추가로 파라미터를 넘길 수 있다.


✨ 예제 2

<!-- PostCreate.vue 자식 컴포넌트 -->

<template>
  <div>
    <button @click="$emit('createPost', '토끼는', '개발개발'"></button> <!-- 자식에서 부모로 이벤트 'createPost'내보내기 -->
  </div>
</template>
<!-- TheView.vue 부모 컴포넌트 -->

<template>
  <div>
    <PostCreate @create-post="callFunction" ></PostCreate> <!-- 부모에서 이벤트 수신 -->
  </div>
</template>
<script>
  const callFunction = (word1, word2) => {
  	console.log(word1, word2); // 토끼는 개발개발 출력
  }
</scritp>

예제2처럼 컴포넌트 내장메서드 $emit을 사용할 수도 있고,
setup함수의 context.emit을 사용하여 스크립트에서 처리할 수도 있다.

✨ 예제 3

<!-- PostCreate.vue 자식 컴포넌트 -->

<template>
  <div>
    <button @click="createPost"></button> 
  </div>
</template>
<script>
export default{
  setup(props, {emit}){ //context.emit 구조분해할당
	const createPost = () => {
    	emit('createPost', '토끼는', '개발개발');
    }
    return { createPost};
  }
}
</scritp>



3. 이벤트 선언

vue3에서는 emits 옵션을 사용하여 이벤트를 선언할 수 있다.
이벤트 선언 방법에는 (1) 문자열 배열 선언, (2) 객체 문법 선언 두 가지 형식이 있다.

(1) 문자열 배열 선언

emits에 이벤트를 문자열 배열로 선언하였다.

✨ 예제 4

<script>
export default{
  emits: ['createPost']
  setup(props, {emit}){ //context.emit 구조분해할당
    emit('createPost', '토끼는', '개발개발');
  }
}
</scritp>

(2) 객체 문법 선언

객체문법으로 선언할 경우 validation 로직을 추가할 수 있다. 만약 validation이 없다면 null로 설정하면 된다.

✨ 예제 5

<script>
export default{
  emits: {
          // 유효성 검사가 없는 이벤트 선언
          createPost: null,

          // 유효성 검사가 있는 이벤트 선언
          createPost: newTitle => {
              console.log(newTitle);
              if(!newTitle){
              	return false;
              }
              return true;
          }
        }
	},
  setup(props, {emit}) {
    context.emit('createPost', '토끼는', '개발개발')
  }
}
</scritp>

이벤트 선언 방법 두 가지에 대해 알아봤다.
자, 그럼 이제 의문점이 하나 생겼을 것이다.

"왜 이벤트를 선언해야 하는가?"

선언하지 않아도 잘 돌아가는데 왜 emits로 이벤트를 선언해야 하는지에 대한 의문 말이다.

선택사항이겠지만, 다음과 같은 이유가 있다.
① 컴포넌트가 작동하는 방식을 더 잘 문서화 하기 위해
② 또한, vue가 non-prop 속성에 알려진 리스너(Fallthrough)를 제외할 수 있다.




참고문헌

vue공식문서
vue3 완벽정리(기본편) - 짐코딩


오늘의 한 줄

이벤트 선언 부분에서, 이벤트를 선언하지 않아도 잘 돌아가는데 '왜 이벤트를 선언해야하는가?'에 대한 답으로 컴포넌트의 문서화를 답했다.

컴포넌트의 문서화, 다시 말해 읽기 편하고 유지보수가 쉬운 코드.
내가 실무에서 nexacro -> vue 전환 프로젝트에서<개발 표준>에 대해 고민하며 굉장히 중요하다고 생각했던 부분이다.
전환 프로젝트뿐만 아니라 모든 업무에 있어서도 중요하다고 생각하는 부분이다.

개발을 혼자 공부하던 취준생 시절 '가독성이 좋은 코드', '유지보수가 쉬운 코드'에 대해 대충 감으로만 느꼈었는데 이게 얼마나 중요한지 개발 업무를 하며 깨달았다.

단순히, 짧고 간결한 코드가 좋은 코드가 아니다.
타개발자가 내 코드를 봤을 때 얼마나 직관적으로 빠르고 명료하게 그 컴포넌트의 기능과 구현을 읽어낼 수 있느냐가 포인트다.

특정 기능을 수정해야 할 때 그 기능들이 어디에 어떻게 구현되어 있으며 선언된 변수들과 함수들은 어떤 역할을 하고있는지 명확하게 파악할 수 있는 것이 진짜 좋은 코드라고 생각한다.

아 이거 정말 중요하다.
나만 볼 수 있는 구조와 명명으로 나만 편하게 작성해놓으면
내 코드를 수정하러 온 동료는 매우 빡이 칠 것이다.

내 동료를 화나게 하지말자..!

profile
하이 이것은 나의 깨지고 부서지는 샏 스토리입니다

0개의 댓글