vue.js/Vue3 - 기본편

22. Non-Prop 속성 (fallthrough 속성)

DEV-Front 2024. 2. 4. 23:43
반응형

Non-Prop 속성 (fallthrough 속성)

 

Non-Prop 속성은 props 또는 event에 명시적으로 선언되지 않은 속성 또는 이벤트 입니다.

예를 들어 class, style, id와 같은 것들이 있습니다.


속성 상속

컴포넌트가 단일 루트 요소로 구성되어 있으면 fallthrough 속성은 루트 요소의 속성에 자동으로 추가됩니다.

예를들어 <MyButton> 이라는 컴포넌트가 있다고 가정해보겠습니다.

 

그리고 이 컴포넌트를 사용하는 부모 컴포넌트는 다음과 같습니다.

 

최종 렌더링된 DOM은 다음과 같습니다.

최종 렌더링은 자식 컴포넌트의 루트 엘리먼트에 이렇게 상속됩니다.

 

루트 엘리먼트란? 컴포넌트의 template 태그 속에서 제일 상위 요소입니다.

예: template 바로 밑에 있는 div가 루트 엘리먼트 입니다.


Class, Style 속성 병합

 

만약 자식 컴포넌트 루트 요소에 이미 class와 style 속성이 정의되어 있으면,

부모로 받은 class와 style 속성과 병합합니다.

 

최종 병합된 DOM은 다음과 같습니다.


v-on 이벤트 리스너 상속

 

v-on 이벤트 리스너도 동일하게 상속됩니다.

  • @click 리스너는 <MyButton>의 컴포넌트 루트요소인 <button>요소에 추가됩니다.
  • 만약 <button> 요소에 이미 바인딩된 이벤트가 있다면 이벤트가 추가되어 두 리스너 모두 트리거 됩니다.

속성 상속 비활성화

 

컴포넌트가 자동으로 Non-Prop 속성을 상속하지 않도록 하려면 컴포넌트의 inheritAttrs : false 옵션을 설정할 수 있습니다.

컴포넌트에 Non-Prop 속성을 비활성화 하는 일반적인 경우는 자식 컴포넌트의 루트요소에 이외의 다른 요소에

Non-Prop 속성을 적용하고 싶을 때 입니다.

 

그리고 적용해야 하는 요소에 <template> 에서 Non-Prop속성에 접근할 수 있는 내장 객체 $attrs로 직접 

접근할 수 있습니다.

$attrs 객체에는 컴포넌트에 선언되지 않은 모든 속성 props, emit (예: class, style, v-on등) 을 포함하고 있습니다.

 

 

몇 가지 참고사항 :

  • props와 달리 Non-Prop 속성은 JavaScript에서 원래 대소문자를 유지하므로 foo-bar 와 같은 속성은 $attrs['foo-bar'] 접근해야 합니다.
  • @click과 같은 v-on 리스너는 $attrs.onClick과 같이 함수로 접근할 수 있습니다.

 

 

 

사용되는 예를 들자면 부모 컴포넌트에서 자식 컴포넌트로 style, class를 내리는데

자식 컴포넌트의 루트 엘리먼트가 class, style을 받아와야 하는 엘리먼트가 아니게 마크업 되어있을 수 있다.

button 태그에 class, style을 적용하려는데 루트 엘리먼트는 div다.

div태그에 button관련 class가 상속된 모습

이럴때 inheritAttrs를 사용할 수 있다.

 

inheriAttrs를 적용했더니 속성 상속이 안되는 모습.

 

속성 상속을 안했는데 부모에서 내려주는 class, id, style을 자식 컴포넌트의 button에 적용하고 싶다면?

이럴때 내장 객체인 $attrs 를 사용해서 우리가 바인딩 해올수 있다.

 

 

attrs의 console 출력 내용

 

setUp() 함수에서 접근하는 방법은 context를 받아와서 attrs 속성을 사용하는거다,.

&attrs에는 요소의 id, class, style과 함수들이 다 들어있음.

 

그래서 v-bind만 하고 attrs 객체를 넘기게 되면 자동 속성 바인딩이된다.

 

 

원하는대로 자식 컴포넌트의 button 태그에 부모에서 내려준 class가 적용된 모습

 

 

Vue2의 $listeners 객체가 Vue3에서 $attrs의 일부가 되었습니다.

Vue3에서는 $listeners 객체가 제거 되었습니다.

속성이랑 이벤트 모두 attrs 객체에 포함 되었습니다.


 

Non-Prop 속성을 특정 요소에 모두 적용하기

 

inheritAttrs : false 와 $attrs를 이용하면 Non-Prop 속성을 특정 요소에 모두 적용할 수 있습니다.

<template>
  <label>
    이름:
    <input type="text" v-bind="$attrs" />
  </label>
</template>
<script>
export default {
  inheritAttrs: false,
};
</script>

 

부모 컴포넌트

<MyInput
  class="my-input"
  placeholder="didj"
  @keyup="onKeyup"
  data-message="Hello World!"
/>

 

 


Fragment

Vue3에서 컴포넌트는 다중 루트 노드 컴포넌트인 fragments를 공식 지원합니다.

 

Vue2.x 문법

2.x에서는 다중 루트 컴포넌트가 지원되지 않았고, 사용자가 실수로 다중 루트 컴포넌트를 만들었을 경우

경고 메시지를 보냈습니다. 그리고 이 오류를 해결하기 위해 컴포넌트가 단일 <div>로 감싸게 됐습니다.

 

Vue3.x 문법

3.x에서 컴포넌트는 다중 루트 노드(multiple root node)를 가질 수 있습니다.

하지만, 개발자가 속성을 배포(상속) 해야 하는 위치를 명시적으로 정의해야 합니다.


여러 루트노드의 속성 상속

 

단일 루트 요소가 있는 컴포넌트와 달리 여러 루트요소가 있는 컴포넌트에서는 자동으로 Non-Prop 속성이 상속되지 

않습니다. 만약 명시적으로 $attrs를 바인딩하지 않을 경우 런타입 경고가 발생됩니다.

<!-- CustomLayout.vue -->
<template>
  <header></header>
  <main></main>
  <footer></footer>
</template>

 

부모 컴포넌트

<CustomLayout id="custom-layout"></CustomLayout>

 

$attrs이 명시적으로 바인딩된 경우는 경고표시가 되지 않습니다.

<!-- CustomLayout.vue -->
<template>
  <header></header>
  <main v-bind="$attrs"></main>
  <footer></footer>
</template>

 

 

 

반응형

'vue.js > Vue3 - 기본편' 카테고리의 다른 글

24. Provide / Inject  (0) 2024.02.11
23. Slot  (0) 2024.02.05
21. Events  (0) 2024.02.04
20. Props  (0) 2024.01.29
19. Single File Component (SFC) | 언어블록 | CSS 기능  (0) 2024.01.28