본문 바로가기
프론트엔드/Vue

(Vue 3) non-emits event 경고

by bellmir 2022. 1. 16.

(Vue 3) non-emits event 경고

 

Vue로 프로젝트를 개발하다 보니 팝업창을 띄울 때마다 런타임시 이상한 경고창이 뜨는 것을 발견했다.

 

Extraneous non-emits event listeners (closePopup) 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.

 

왜 이런 경고창이 뜨는 것일까?

내가 진행하던 프로젝트에서 경고창이 나오는 부분을 간소하게 나타내면 다음과 같았다.

// 부모 컴포넌트에서 'Popup'이라는 자식 컴포넌트를 사용
<Popup
  v-if="showPopup"
  @closePopup="closePopup"
/>
// 자식인 Popup 컴포넌트
<template>
  <div class="screen_filter"></div>
  <div class="popup">
    ...
  </div>
</template>

<script>
export default {
  methods: {
    closePopup(){
      this.$emit('closePopup');
    }
  }
}
</script>

 

이게 동작은 하는데 거슬려서 구글에 검색해보니 아래의 글을 발견할 수 있었다. (유튜브에서 강의영상으로 자주 보이시던 코딩애플님이 답변달으신 거라 반가웠다. 내적친밀감ㅋㅋ)

 

https://codingapple.com/forums/topic/emit-listener-%EA%B2%BD%EA%B3%A0/

 

Vue3 Extraneous non-emits event listeners 경고 - 코딩애플 온라인 강좌

구글에서 전부 listener 문제로 찾았다가 선생님 덕분에 한방에 해결... 다시 확인해보니 제 실수로 추가한 글 작성 페이지 탭 HTML들을 기존에 감싼 <div>에 안 넣었네요. 덕분에 해결하고 주의할 것

codingapple.com

 

해결방법

해결방법은 자식요소인 'Popup' 컴포넌트의 <template></template>안의 태그들을 하나의 태그(루트노드)로 묶으면 되는 것이었다.

// Popup 컴포넌트
<template>
  <div>
    <div class="screen_filter"></div>
    <div class="popup">
      ...
    </div>
  </div>
</template>

자식 컴포넌트인 popup 컴포넌트를 하나의 <div> 태그로 묶어 단일 루트 노드 컴포넌트로 만드니 경고창이 뜨지 않는다.

 


 

원인

해결은 됐는데...원인이 뭘까? 내가 나름 생각한 이유는 이렇다.

Vue가 Vue2에서는 'template'안에는 하나의 루트노드만이 있어야 했다고 들었다. 이게 Vue3에 와서는 여러 태그들을 사용해도 상관 없게 바뀌었다고 알고있는데, 뭔가 아직 하나의 태그만 있을 때 온전히 동작하는게 있어서 경고창이 뜨는게 아닐까는 생각이 들었다.

 

공식 문서를 찾아보니 'Non-Props' 속성을 설명하는 페이지의 '다중 루트 노드의 속성 상속'부분에서 힌트를 얻었다.

 

URL 너무길어 링크로 대체 (다중 루트 노드의 속성 상속)

 

Non-Prop 속성 | Vue.js

Non-Prop 속성 이 페이지는 여러분이 이미 컴포넌트 기초를 읽었다고 가정하고 쓴 내용입니다. 컴포넌트가 처음이라면 기초 문서를 먼저 읽으시기 바랍니다. 컴포넌트 non-prop 속성은 컴포넌트에

v3.ko.vuejs.org

컴포넌트 non-prop 속성은 컴포넌트에 전달되지만, props나 emits에 정의된 특성을 지니고 있지 않은 속성 또는 이벤트 리스너를 의미합니다

(중략)
단일 루트 노드 컴포넌트와 달리 다중 루트 노드 컴포넌트는 자동으로 속성을 아래로 전달하는 동작(fallthrough behavior)을 하지 않습니다. $attrs가 명시적으로 바인딩되지 않으면, 런타임 경고가 발생합니다.

 

내 프로젝트의 경우 부모 컴포넌트에서 'closePopup'이라는 이벤트가 'popup' 컴포넌트에 바인딩 되어있는데, popup컴포넌트가 다중 루트 노드 컴포넌트이기 때문에 런타임 경고를 일으키는 것이었다. 따라서 하나의 태그로 묶어줘서 단일 루트 컴포넌트로 만들면 해결됐던 것이다!

 

 

결론

자식 컴포넌트로 Non-Props 속성을 상속할 땐 자식 컴포넌트를 단일 루트 노드 컴포넌트로 만들어야 한다. 만일 다중 루트 노드라면 런타임 경고가 발생한다.

오늘도 지식이 늘었다 :)

 

 

* 잘못된 정보 지적은 언제나 환영입니다 :)

 

 

'프론트엔드 > Vue' 카테고리의 다른 글

(Vue 3) Custom v-directive 만들기  (0) 2022.02.21
Vue2에서 clearTimeout & clearInterval 하는법  (0) 2022.01.19

댓글