NodeJS

[NodeJs/VueJs] 슬롯 (Slots)

Question영 2019. 12. 6. 15:57
반응형

저는 개발을 진행할때 기능별로 나누어 놓는 것을 좋아해서

 

UI 기준 기능을 컴포넌트들로 나눠서 관리 합니다.

 

사용할때 나누어 놓은 기능 컴포넌트들을 부모 컴포넌트에 연결해서 사용하죠.

 

그런데 간혹 부모 컴포넌트에서 연결한 컴포넌트 템플릿에

 

HTML 요소가 동적으로 적용되어야 하는 경우가 있습니다.

 

이럴 경우 Slots 을 사용하면 이런 경우 대처가 가능합니다.

 

슬롯은 부모와 연결된 자식 컴포넌트간에 통로 역할을 한다고 생각하면 됩니다.

 

연결된 통로에 동적으로 적용되는 UI 나 이벤트들을 연결하여 사용하는 것이죠.

 

지금부터 다루게 될 내용은 개편된 v2.6 기준 의 내용입니다.

 

Slot(슬롯의 기본)

 

<!-- #1 기본 -->
<!-- 부모 컴포넌트 -->
<content>
슬롯에 들어갈 내용입니다.
</content>
<!-- 연결된 자식(하위) 컴포넌트 content -->
<div>
    <slot></slot>
</div>
<!-- 컴파일 결과 -->
<div>
    슬롯에 들어갈 내용입니다.
</div>

 

슬롯은 자식(하위) 컴포넌트에서 정의한 slot 영역의 구성을 부모(상위) 컴포넌트에 위임하는 방식입니다.

 

이렇게 구성되면서 작업자는 유연하게 대처할수 있고 재사용성이 높아지게 됩니다.

 

Slot Content(슬롯에 들어가는 내용)

 

<!-- #2 컨텐츠에 태그 사용 -->
<!-- 부모 컴포넌트 -->
<content>
  <div>
    슬롯에 들어갈 내용입니다.
  </div>
</content>
<!-- 연결된 자식(하위) 컴포넌트 content -->
<div>
  <slot>
    <p>부모에서 정의한 컨텐츠 내용이 해당 태그를 대체 합니다.</p>
  </slot>
</div>
<!-- 컴파일 결과 -->
<div>
  <div>
    슬롯에 들어갈 내용입니다.
  </div>
</div>

 

부모(상위) 컴포넌트에서 자식(하위) 컴포넌트를 연결할때 태그안에 내용을 정의하면

 

연결 대상이된 자식 컴포넌트에서 slot 영역에 어떠한 html 태그를 정의하더라도 무시가 되고

 

컴파일 결과처럼 오버라이드가 되어버립니다.

 

Named Slots(이름이 있는 슬롯)

 

<!-- #3 지정한 하위 컴포넌트에 동적 위치 -->
<!-- 부모 컴포넌트 -->
<content>
  <template v-slot:header>
    <h1>v-slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  </template>
  기본 슬롯에 위치
</content>
<!-- 연결된 자식(하위) 컴포넌트 content -->
<div>
  <slot name="header">
    v-slot:header 내용으로 대체 됩니다.
  </slot>
  <slot></slot>
</div>
<!-- 컴파일 결과 -->
<div>
  <div>
    <h1>v-slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  </div>
  기본 슬롯에 위치
</div>

 

자식 컴포넌트는 여러개의 슬롯을 가질수 있으며 이름을 부여하여

 

부모 컴포넌트에서 특정한 컨텐츠 태그를 정의할수 있습니다.

 

부모(상위) 컴포넌트 예시에 v-slot 을 이용하여 header 라는 네이밍을 주고 있는 것을 볼수 있습니다.

 

이때 반드시 <template> 라는 태그를 사용해야합니다.

 

<template> 태그를 통해 이름을 부여받지 못한 내용들은 자식 컴포넌트에 정의된 이름 없는 slot 에 위치합니다.

 

이마저도 정의되어 있지 않다면 내용이 무시가 됩니다.

 

Named Slots Shorthand(단축표기)

 

<!-- #4 단축 Slot 키워드 '#' -->
<!-- 부모 컴포넌트 -->
<content>
  <template #header>
    <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  </template>
  <div>기본 슬롯에 위치</div>
  <template v-slot:footer>
    <p>v-slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</p>
  </template>
</content>
<!-- 연결된 자식(하위) 컴포넌트 content -->
<div>
  <slot name="header">
    #header 의 내용으로 대체 됩니다.
  </slot>
  <slot></slot>
  <slot name="footer">
    v-slot:footer 내용으로 대체 됩니다.
  </slot>
</div>
<!-- 컴파일 결과 -->
<div>
  <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  <div>기본 슬롯에 위치</div>
  <p>v-slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</p>
</div>

v-on(@)v-bind(:)처럼 v-slot도 단축표기를 가지고 있습니다.

 

인수 앞에 쓰는 부분(v-slot:)을 특수 기호인 #으로 대체하는 것입니다.

 

예제에서 보듯이 header 와 footer 는 지정된 슬롯 위치에 배치되는 것을 확인할 수 있습니다.

 

Scoped Slots(슬롯의 범위 연결)

 

<!-- #5 범위 연결 후 요소 및 이벤트 사용 -->
<!-- 부모 컴포넌트 -->
<content>
  <template #header="slotProps">
    <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
    <button @click="slotProps.open">열기</button>
  </template>
  <template #footer="footerSlotProps">
    <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
    <button @click="footerSlotProps.close">닫기</button>
  </template>
</content>
<!-- 연결된 자식(하위) 컴포넌트 content -->
<template>
<div>
  <div>
    <slot name="header">
      #header 의 내용으로 대체 됩니다.
    </slot>
    <slot name="footer">
      v-slot:footer 내용으로 대체 됩니다.
    </slot>
  </div>
</div>
</template>

<script>
export default {
  name: "Slots",
  // <!-- 속성 및 매서드 -->
  data: {
    // 사용하는 데이터를 정의
    isOpen: false
  },
  methods: {
    // 사용하는 함수들을 정의
    open () {
      console.log('run open')
      isOpen = true
    },
    close () {
      console.log('run close')
      isOpen = false
    }
  }
}
</script>

 

부모 컴포넌트의 슬롯에서 자식 컴포넌트에서 정의된 요소를 사용하고 싶은 경우가 있습니다.

 

상태값을 변경하거나, 정의된 이벤트를 사용한다던가 말이죠.

 

<template #header="slotProps">

<slot> 요소에 연결된 속성을 슬롯 속성(slot props)라고 합니다.

 

부모 컴포넌트 예제를 보면 위와 같이 slotProps 라는 키워드로 슬롯 범위를 설정하였습니다.

 

저렇게 선언된 스코프 범위에서는 연결된 자식 컴포넌트의 요소를 연결하여 사용할수 있습니다.

<template #footer="footerSlotProps">

 

스코프를 선언할때 사용되는 슬롯 속성(slotProps) 이름은 위와 같이 사용자가 변경할 수 있습니다.

 

Dynamic Slot Names (가변 슬롯 이름)

 

<!-- #6 동적인 슬롯명 사용 -->
<!-- 부모 컴포넌트 -->
<content>
  <template v-slot:[header]> <!-- 동적인 슬롯명 --> 
    <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  </template>
</content>

or

<content>
  <template #[header]> <!-- 동적인 슬롯명 --> 
    <h1>#slot 에서 정의한 이름의 슬롯에 들어갈 내용입니다.</h1>
  </template>
</content>

 

가변 슬롯 이름을 정의하는 방식으로 v-slot에서도 작동합니다.

 

<template #[header]> <!-- 동적인 슬롯명 --> 

 

여기서 header 는 동적 변수라고 생각하면 됩니다.

 

만약 header 에 footer 라고 문자열이 부여가 되어 있다면

 

<template #footer> <!-- 실제 부여된 슬롯명 -->

 

실제 저런식으로 적용이되고 있을 것입니다.

 

슬롯에 대해 간략하게 살펴봤습니다.

 

재사용성을 높이 동적 구성과 유연한 작업을 하기 위해 Slot 은 대단히 유용한 기능이니

 

공부해서 사용해보시길 권장드립니다.


참고자료

반응형