한 번에 끝내는 프론트엔드 개발 초격차 패키지 Online를 들으며 정리한 내용입니다.
부모 컴포넌트의 html 요소에 class나 기타 속성들이 자식 컴포넌트의 하나의 요소에 연결되는 것을 속성 상속이라고 합니다.
App.vue
<template>
<MyBtn class="heory" style="color: red">
Banana
</MyBtn>
</template>
<script>
import MyBtn from '~/components/MyBtn'
export default {
components: {
MyBtn
}
}
</script>
MyBtn.vue
<template>
<div class="btn">
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped lang="scss">
.btn {
display: inline-block;
margin: 4px;
padding: 6px 12px;
border-radius: 4px;
background-color: gray;
color: white;
cursor: pointer;
}
</style>
개발자도구를 열어 확인해보면, 부모 컴포넌트의 MyBtn에 해당하는 클래스 속성의 값과 스타일이 해당하는 자식 컴포넌트의 div부분에 적용이 되었음을 알 수 있습니다.
여기서 주의해야할 부분이 있습니다. 하나의 컴포넌트 같은 경우template
태그 사이에 하나의 html구조를 작성하게 됩니다. 이 템플릿의 바로 자식요소를 해당하는 컴포넌트의 최상위 요소(루트요소)라고 부릅니다.
<template>
<div class="btn"> //최상위 요소(루트요소)
<slot></slot>
</div>
<div></div> //최상위 요소(루트요소)
</template>
위와 같이 자식 컴포넌트에 div요소를 하나 더 추가를 하면 MyBtn이라는 컴포넌트는 최상위요소가 2개가 있는 상태가 되게 되어, 부모 컴포넌트에 입력한 속성 값이 어느 부분에 상속이 되어야하는지 판단할 수 없기 때문에 두 요소 모두 상속이 되지 않게 됩니다.
따라서 자식 컴포넌트의 최상위요소가 2개가 있는 경우 부모 컴포넌트에 입력한 속성의 내용들이 자식 컴포넌트의 어느 부분에 상속이 되어야하는지를 정의해주어야합니다.
자식 컴포넌트의 script부분에 속성의 상속을 지정해주는 옵션인inheritAttrs
속성을 이용해 하나의 방식으로 정리를 해줄 수 있습니다.
MyBtn.vue
<script>
export default {
inheritAttrs: false
}
</script>
inheritAttrs: false
값을 준 후 확인을 해보면 최상위요소가 하나밖에 없음에도 부모 컴포넌트에 입력한 속성들이 상속되고 있지 않은 것을 확인할 수 있습니다.
이렇게 inheritAttrs: false
을 통해 처음부터 어떠한 속성들도 상속하지 않는 상태로 만든 후 프로젝트를 시작할 수 있습니다.
이러한 옵션이 추가되어 있거나 최상위 요소가 여러개가 있어서 속성상속을 받을 수 없는 구조에서, 부모 컴포넌트에 작성되어 있는 여러가지 속성들을 특정한 요소에다 직접적으로 연결해주고 싶다면 created
라이프사이클과 $attrs
객체를 활용할 수 있습니다.
MyBtn.vue
<script>
export default {
inheritAttrs: false,
created() {
console.log(this.$attrs)
}
}
</script>
created라이프사이클을 통해 컴포넌트가 생성된 직후에 컴포넌트가 가지고 있는 $attrs 특정객체를 출력해볼 수 있습니다.
개발자도구를 확인해보면 하나의 데이터처럼 내용이 구성되어 있는 것을 확인할 수 있습니다.이렇게 부모컴포넌트의 속성의 내용들이 this의 $attrs라는 특정한 객체에 저장되어서 확인을 할 수 있도록 만들어줍니다.
그러면 이러한 내용이 특정한 요소에 적용이 될 수 있도록 만들어줍니다.
MyBtn.vue
<template>
<div class="btn">
<slot></slot>
</div>
<h1
:class="$attrs.class"
:style="$attrs.style"></h1>
</template>
해당 클래스의 값과 스타일이 잘 들어간 것을 확인할 수 있습니다.
이렇게 루트 엘리먼트가 하나 이상이거나, 하나밖에 없을 때 그것을 상속하지 않는 옵션을 정리해준 후에 실제 들어오는 속성들을 원하는 요소에 연결해줄때 $attrs객체를 활용할 수 있습니다.
또한 이렇게 하나의 요소에 해당하는 내용을 모두 적용하는 경우에는 v-bind속성을 추가해 아래와 같이 작성해주어도 됩니다.
단, v-bind를 :와 같은 약어로 사용해서는 안됩니다.
<h1 v-bind="$attrs"></h1>