[Vue]Slots

chaewonยท2024๋…„ 7์›” 23์ผ
0
post-thumbnail
post-custom-banner

๐Ÿ’ป Slots

HTML ์š”์†Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ฝ˜ํ…์ธ ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์œ ์šฉํ•˜๋‹ค. <FancyButton>์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“  ํ›„ ์ฝ˜ํ…์ธ ๋ฅผ ์ „๋‹ฌํ•ด๋ณด์ž.

<!-- FancyButton.vue -->
<template>
  <button class="fancy-btn">
  	<slot></slot>
  </button>
</template>

-> Style
์œ„์— ์ •์˜ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์‚ฌ์šฉํ•ด๋ณด์ž

<FancyButton>
	<!-- ์Šฌ๋กฏ ์ฝ˜ํ…์ธ  -->
  	Click!!
</FancyButton>

slot ์š”์†Œ๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ์ฝ˜ํ…์ธ ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์Šฌ๋กฏ์€ ํ…์ŠคํŠธ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ HTML์š”์†Œ, ์ปดํฌ๋„ŒํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ชจ๋“  ์ฝ˜ํ…์ธ ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

Named Slots

<slot> ์š”์†Œ์— ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜์—ฌ ์—ฌ๋Ÿฌ๊ฐœ์˜ <slot>์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

<!-- BaseCard.vue -->
<template>
  <article>
    <div>
      <slot name="header"></slot>
    </div>
    <div>
      <slot></slot>
    </div>
    <div>
      <slot name="footer"></slot>
    </div>
  </article>
</template>
  • slot์— name ์†์„ฑ์„ ๋ถ€์—ฌํ•˜์—ฌ ํŠน์ • ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ๊ฐ€ ๋ Œ๋”๋ง ๋˜์–ด์•ผ ํ•  ์œ„์น˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • name์ด ์—†๋Š” <slot>์˜ ์ด๋ฆ„์€ ์•”์‹œ์ ์œผ๋กœ default๋‹ค.
<!-- ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ ์˜ˆ์‹œ -->
<template>
  <BaseCard>
    <template v-slot:hedaer>์ œ๋ชฉ</template>
    <template v-slot:default>๋‚ด์šฉ</template>
    <template v-slot:footer>ํ‘ธํ„ฐ</template>
  </BaseCard>
</template>

์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ name์ด ๋ถ€์—ฌ๋œ <slot>์— ์ฝ˜ํ…์ธ ๋ฅผ ์ „๋‹ฌํ•˜๋ ค๋ฉด v-slot ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  v-slot:์ „๋‹ฌ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ•œ ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

v-slot์€ # ๋‹จ์ถ•ํ‚ค๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์ด์žˆ๋‹ค.

<!-- ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ ์˜ˆ์‹œ -->
<template>
  <BaseCard>
    <template #hedaer>์ œ๋ชฉ</template>
    <template #default>๋‚ด์šฉ</template>
    <template #footer>ํ‘ธํ„ฐ</template>
  </BaseCard>
</template>

๊ทธ๋ฆฌ๊ณ  default ์Šฌ๋กฏ์€ ์•”์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

<!-- ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ ์˜ˆ์‹œ -->
<template>
  <BaseCard>
    <template #hedaer>์ œ๋ชฉ</template>
    <!-- ์•”์‹œ์ ์œผ๋กœ default slot -->
    ๋‚ด์šฉ
    <template #footer>ํ‘ธํ„ฐ</template>
  </BaseCard>
</template>

Render Scope

์Šฌ๋กฏ ์ฝ˜ํ…์ธ ๋Š” ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์— ์ •์˜๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ์ดํ„ฐ ์˜์—ญ์— ์ ‘๊ทผ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์˜ ์˜์—ญ์—๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.

Scoped Slots

Render Scope์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ์—์„œ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์™€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ๊ฐœ๋ฐœํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•˜๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์šฐ๋ฆฌ๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ <slot> ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ props๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์†์„ฑ์„ ์Šฌ๋กฏ ์ฝ˜ํ…์ธ ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

<!-- MyComponent.vue -->
<template>
  <div>
    <slot :text="greetingMessage" :count="count"></slot>
  </div>
</template>

<script>
  import { ref } from 'vue';
  
  export default {
  	setup() {
  		const greetingMessage = ref('Hello!!');
  		const count = ref(1);
  		return{ greetingMessage, count};
  	},
  };
</script>
profile
์˜๋ฌธ์€ '์‚ถ์˜ ์ˆ˜์ค€'์„ ๊ฒฐ์ •ํ•˜๊ณ , ์งˆ๋ฌธ์€ '์‚ถ ์ž์ฒด'๋ฅผ ๋ฐ”๊พผ๋‹ค.
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€