Web Development/vue

[콜럼Vue스] 슬롯 (Slots)

쟤리 2024. 10. 14. 07:23
728x90
반응형

Vue.js에서 슬롯은 부모 컴포넌트가 자식 컴포넌트 내부의 특정 위치에 콘텐츠를 동적으로 전달할 수 있도록 도와주는 메커니즘임.

이 기능을 활용하면 컴포넌트의 재사용성이 극대화되고 더 유연한 설계가 가능해짐


슬롯 사용 전의 컴포넌트

슬롯을 사용하지 않는 컴포넌트는 자식 컴포넌트의 구조와 콘텐츠가 고정되어, 재사용에 한계가 생김

<!-- src/components/NoSlotTest.vue -->
<template>
  <div>
    <input type="checkbox" :value="id" :checked="checked" 
      @change="$emit('check-changed', { id, checked: $event.target.checked })" />
    <span :style="{ color: checked ? 'blue' : 'gray' }">
      <i>{{ label }}</i>
    </span>
  </div>
</template>

<script>
export default {
  name: "NoSlotTest",
  props: ["id", "checked", "label"]
};
</script>

슬롯의 기본 사용법

기본 슬롯을 사용하면 부모 컴포는트가 동적으로 컨텐츠를 전달할 수 있음

자식 컴포넌트는 <slot> 태그로 부모가 전달한 콘텐츠를 표시

예제 - 기본 슬롯 사용

<!-- src/components/CheckBox1.vue -->
<template>
  <div>
    <input type="checkbox" :value="id" :checked="checked" 
      @change="$emit('check-changed', { id, checked: $event.target.checked })" />
    <slot>기본 아이템</slot>
  </div>
</template>

<script>
export default {
  name: "CheckBox1",
  props: ["id", "checked"]
};
</script>

부모 컴포넌트에서의 사용 예시

<template>
  <CheckBox1 v-for="item in items" :key="item.id" :id="item.id"
             :checked="item.checked" @check-changed="CheckBoxChanged">
    <span :style="{ color: item.checked ? 'blue' : 'gray' }">
      <i>{{ item.label }}</i>
    </span>
  </CheckBox1>
</template>

<script>
import CheckBox1 from './components/CheckBox1.vue';

export default {
  components: { CheckBox1 },
  data() {
    return {
      items: [
        { id: 'V', checked: true, label: 'Vue' },
        { id: 'A', checked: false, label: 'Angular' },
        { id: 'R', checked: false, label: 'React' },
      ]
    };
  },
  methods: {
    CheckBoxChanged(e) {
      let item = this.items.find((item) => item.id === e.id);
      item.checked = e.checked;
    }
  }
};
</script>

명명된 슬롯 (Named Slots)

명명된 슬롯은 자식 컴포넌트의 여러 위치에 다양한 콘텐츠를 삽입할 때 유용

슬롯마다 이름을 부여해 부모 컴포넌트에서 해당 위치에 적합한 내용 전달 가능

명명된 슬롯 사용

<!-- src/components/CheckBox2.vue -->
<template>
  <div>
    <slot name="icon"></slot>
    <input type="checkbox" :value="id" :checked="checked" 
      @change="$emit('check-changed', { id, checked: $event.target.checked })" />
    <slot name="label">기본 레이블</slot>
  </div>
</template>

<script>
export default {
  name: "CheckBox2",
  props: ["id", "checked"]
};
</script>

부모 컴포넌트에서의 사용 예시

<template>
  <CheckBox2 v-for="item in items" :key="item.id" :id="item.id"
             :checked="item.checked" @check-changed="CheckBoxChanged">
    <template #icon>
      <i :class="item.checked ? 'fas fa-check-circle' : 'fas fa-circle'"></i>
    </template>
    <template #label>
      <span :style="{ color: item.checked ? 'blue' : 'gray' }">
        {{ item.label }}
      </span>
    </template>
  </CheckBox2>
</template>

범위 슬롯 (Scoped Slots)

범위 슬롯은 자식 컴포넌트가 부모 컴포넌트에게 데이터를 전달할 때 사용

이를 통해 부모 컴포넌트는 자식 컴포넌트에서 제공한 데이터를 활용해 동적인 UI 구성 가능

예제 - 범위 슬롯 사용

<!-- src/components/CheckBoxList.vue -->
<template>
  <div v-for="item in items" :key="item.id">
    <slot :item="item"></slot>
  </div>
</template>

<script>
export default {
  name: "CheckBoxList",
  props: ["items"]
};
</script>

부모 컴포넌트에서의 사용 예시

<template>
  <CheckBoxList :items="items">
    <template #default="{ item }">
      <input type="checkbox" :value="item.id" :checked="item.checked"
             @change="CheckBoxChanged(item)" />
      <span :style="{ color: item.checked ? 'blue' : 'gray' }">
        {{ item.label }}
      </span>
    </template>
  </CheckBoxList>
</template>

<script>
import CheckBoxList from './components/CheckBoxList.vue';

export default {
  components: { CheckBoxList },
  data() {
    return {
      items: [
        { id: 'V', checked: true, label: 'Vue' },
        { id: 'A', checked: false, label: 'Angular' },
        { id: 'R', checked: false, label: 'React' },
      ]
    };
  },
  methods: {
    CheckBoxChanged(item) {
      item.checked = !item.checked;
    }
  }
};
</script>

Vue.js에서 슬롯은 컴포넌트 간의 유연한 데이터 및 콘텐츠 전달을 가능하게 하는 중요한 기능임

- 기본 슬롯은 단순한 콘텐츠 전달에 적합

- 명명 슬롯은 여러 위치에 서로 다른 콘텐츠를 삽입할 때 유용

- 범위 슬롯은 자식 컴포넌트가 부모에게 데이터를 제공해 보다 동적인 UI 구성 도움

728x90
반응형