[데브코스/TIL] DAY90 - Vue(6) slot & composition api

Minha Ahn·2025년 1월 11일
0

데브코스

목록 보기
41/42
post-thumbnail

✅ 컴포넌트 슬롯

1. 슬롯이란

  • 컴포넌트의 특정 영역을 대체하는 기술
  • 리액트의 Children과 동일한 역할
    • 부모가 템플릿 조각을 자식 컴포넌트에 전달
    • 자식 컴포넌트가 전달받은 템플릿 조각을 렌더링할 수 있게 하는 기능
  • 슬롯을 설정해두지 않으면 자식 컴포넌트로 감싸도 렌더링되지 않음
  • 부모 컴포넌트에서 동일한 슬롯 이름으로 여러번 호출 시, 마지막 요소만 적용

2. 슬롯 사용 방식

이름이 없는 슬롯

  • <slot></slot>
  • 자식 컴포넌트 사이에 들어가는 콘텐츠가 <slot></slot> 대신에 들어가게 됨
// 부모 컴포넌트
<Button>버튼</Button>

// Button 컴포넌트
// <slot></slot> 대신 버튼이 들어감
<slot></slot>

이름이 있는 슬롯

  • <slot name="값"></slot>
  • 부모 컴포넌트에서 v-slot으로 전달하는 값과 자식 컴포넌트의 name이 동일한 곳에 콘텐츠가 대신 들어감
  • 단, 부모 컴포넌트에서의 v-slot 는 반드시 <template> 태그에 선언해야 함
  • 일치하는 슬롯이 없으면 보여지지 않음
  • 축약형 : v-slot:값#값
// 부모 컴포넌트
<template v-slot:>
	어쩌구 저쩌구
</template>

// Layout 컴포넌트
<slot name=""></slot>

혼합 슬롯

  • 이름이 없는 슬롯 + 이름이 있는 슬롯을 함께 사용하는 것
  • <slot></slot>name="default"가 자동으로 적용된 상태
  • v-slot 혹은 #으로 넘어오는 값이 유효하지 않거나 없는 경우, default로 정의된 slot에 들어감
<slot name="name"></slot>
<slot></slot> // 디폴트

슬롯의 기본값

  • 부모에서 콘텐츠 없이 자식 컴포넌트만 호출한 경우, 보여질 기본값
  • 콘텐츠가 있다면 기본값은 적용되지 않음
// 부모 컴포넌트
<Child></Child> // "기본값"으로 렌더링
<Child>안녕</Child> // "안녕"으로 렌더링

// Child 컴포넌트
<slot>기본값</slot>

동적 슬롯

  • 슬롯의 이름을 동적으로 지정하는 것
  • 동적으로 지정한다 === 슬롯의 이름을 변수로 지정해 넣는다
  • 자식 컴포넌트의 slot 이름은 지정이 되어야함
  • v-slot="데이터" 아님 유의
<template v-slot:[dynamicName]></template>
<template #[dynamicName]></template>

슬롯 기본 범위

  • 정리) 스타일, 데이터 모두 기본적으로 부모 컴포넌트의 영향을 받음
  • 슬롯 자리에 들어가 렌더링 되는 요소는 각각 고유한 범위가 있음
  • 슬롯의 스타일은 부모 컴포넌트의 영향을 받음
    • 부모에서 사용된 요소들은 자식 컴포넌트 스타일이 적용되지 않음
  • 슬롯의 데이터는 부모 컴포넌트의 영향을 받음
    • 부모에는 없으면서 자식에는 있는 데이터를 사용하는 경우에도 전혀 적용되지 않음
  • 슬롯의 범위를 지정하면 자식 컴포넌트의 데이터 사용 가능

슬롯 범위 지정

  • 자식 컴포넌트의 범위에 접근할 수 있는 방법 제공
    • 부모에 전달할 데이터를 슬롯에 v-bind로 미리 정의 (computed를 포함한 모든 데이터 가능)
    • 부모는 전달된 데이터를 v-slot을 통해 객체 형식으로 받음
// 자식 컴포넌트
// 데이터는 이미 정의되었다고 가정
<slot :childData="childData"></slot>

// 부모컴포넌트
// 자식 컴포넌트가 전달하는 데이터들은 객체 형식으로 받음
// 받을 데이터 명은 원하는대로 지정 가능
<Child v-slot="myKey">{{ myKey.childData }}</Child>

// 객체 분할로 사용 가능
<Child v-slot="{ childData }">{{ childData }}</Child>
  • 이름있는 슬롯으로 사용할 경우 아래와 같음
// 자식 컴포넌트
<slot name="section" :childData="childData"></slot>

// 부모 컴포넌트
<Child #section="myKey">{{ myKey.childData }}</Child>
<Child #section="{ childData }">{{ childData }}</Child>



✅ 컴포지션 API

  • Vue3에 추가된 문법 ⇒ setUp() 훅을 통해 사용 가능
  • Vue3.2에 추가된 설탕 문법 ⇒ <script setup></script>

1. 반응형 데이터, ref와 reactive

  • ref : 기본 자료형을 반응형 데이터로 정의할 때
  • reactive : 참조 자료형을 반응형 데이터로 정의할 때
    • 기본 자료형은 변경 감지 안 됨

script 내부에서 반응형 데이터 접근

  • ref로 정의된 데이터는 value를 통해서 접근
  • reactive로 정의된 데이터는 일반 객체처럼 접근
<script setup>
  import { computed, reactive, ref } from 'vue';
  
	const count = ref(0);
	const array = reactive([1, 2, 3]);
	
	console.log(count.value, array[0]);
</script>

template 내부에서 반응형 데이터 접근

<template>
  <div>{{ count }}</div>
  <div>{{ array[0] }}</div>
</template>

2. 계산된 속성, computed

  • 데이터 가공, 캐싱에 사용 (읽기 전용)
  • computed 함수 사용
  • script 태그 내부에서 사용할 때, value를 통해서 접근
  • template 태그 내부에서는 바로 사용
<script setup>
	import { computed, ref } from 'vue';

  const count = ref(0);
  const doubleCount = computed(() => count.value * 2);
  
  console.log(doubleCount.value)
</script>
<template>
  <div>{{ doubleCount }}</div>
</template>
  • computed 속성을 직접 변경하는 방법 ⇒ get과 set 함수로 세분화
<script setup>
	import { computed, ref } from 'vue';

  const firstName = ref("Minha");
  const lastName = ref("An");
  
  const fullName = computed({
	  get() {
		  return `${lastName.value} ${firstName.value}`
		},
	  set(value) {
		  [lastName.value, firstName.value] = value.split(" ");
		},
  });
</script>
<template>
  <div>{{ doubleCount }}</div>
</template>

3. 함수

  • 함수 선언식, 함수 표현식, 화살표 함수 모두 사용 가능
  • ref, reactive, computed 모두 접근 가능
<script setup>
	import { ref } from 'vue';
	
	const count = ref(0);
	const increment = count.value++;
</script>

4. 감시자 속성 1 - watch

  • 반응형으로 선언된 데이터의 값이 변경되었을 때, 이를 감시하여 코드를 실행시키는 속성
  • 인자 목록
    • 첫번째 인자 : 감시할 반응형 데이터
    • 두번째 인자 : 콜백함수 (감시한 데이터가 변경될 때 실행 / 현재값, 이전값이 순서대로 인자로 들어옴)
    • 세번째 인자 : (선택) 보통 deep 여부 선택.
  • 참조 차료형을 감시하는 경우, 현재값과 이전값이 동일한 점 유의

ref 감시

  • 변수 자체를 감시
  • 기본 : 참조 자료형을 ref로 선언하는 경우, 변경 감지 불가
  • { deep: true } 설정 : 참조 내부까지 변경 감지

reactive 감시

  • 참조 자료형 감시
  • 기본 : 참조 내부까지 변경 감지

옵션

  • deep(true) : 참조 내부까지 감시 (ref)
  • immediate(true) : 처음 디폴트 값을 넣을 때 부터 감시 및 실행 (기본값은 변경될 때만)
  • once(true) : 최초 한 번만 실행
  • flush(선택값) : 감시자가 실행되는 시점 설정
    • pre : (기본값) 감시자가 DOM 업데이트 이전에 실행
    • post : 감시자가 DOM 업데이트 후에 실행
    • sync : 반응형 데이터가 변경되는 즉시 동기적으로 실행 (DOM에 반영 전)

5. 감시자 속성 2 - watchEEffect

  • watch와 비슷한 역할
  • watch와 다른 점
    • deep 옵션 사용하지 않음
    • immediate 옵션을 true로 고정 ⇒ 처음 디폴트 값을 넣을 때 부터 감시 및 실행
    • 감시 대상을 따로 지정하지 않으나, 콜백 함수 내에서 사용하고 있는 반응형 데이터들을 자동 감시
watchEffect(() => {
  console.log(count.value); // count 변수 감시
  console.log(state.count); // state 객체 중에서 count의 변경 감시
  console.log(state); // state의 참조값 변경 감시

6. 감시자 속성 3 - watchPostEffect

  • watchEffect와 flush를 ‘post’의 결합
  • DOM이 갱신된 후 실행

7. 라이프사이클 훅

  • Options API에서 사용하던 beforeCreate()와 create()는 setup 영역으로 대체
  • 나머지 훅은 on + 기존 메서드명 으로 변경

8. props 전달

  • defineProps() 함수를 사용하여 props 받음
<script setup>
  import { defineProps } from 'vue';
  const props = defineProps({
	  count: Number // 여러 자료형을 지정하고 싶다면 [Number, String]
	  text: {
	    type: String,
	    default() { return '기본' }
	})
</script>
<template>
	<p>{{ props.count }}</p>
	<p>{{ props.text }}</p>
</template>

9. 이벤트 받기

  • defineEmits() 함수를 사용하여 이벤트를 받음
<script setup>
  import { defineEmits } from 'vue';
  const emit = defineEmits(['event1', 'event2'])
  
  const handler = () => {
    emit('event1')
  }
</script>
<template>
	<button @click="handler">버튼1</button>
	<button @click="emit('event1')">버튼2</button>
	<button @click="emit('event2', 10, [20])">버튼3</button>
</template>

10. provide & inject

  • props drilling을 방지할 수 있는 방법
  • props를 사용하지 않고 데이터를 전달할 수 있는 방법
  • provide를 사용한 컴포넌트부터 하위 컴포넌트들이 inject로 접근해서 사용 가능
  • 형식
    • provide(고유한 식별자, 제공할 데이터) ⇒ 데이터는 일반, ref, reactive, coumputed 모두 가능
    • const value = inject(고유한 식별자, 기본값) ⇒ 기본값은 생략 가능
<script setup>
	const count = ref(0);
	const array = reactvie([1, 2, 3])
	const increment = () => (count.value++)
	
	provide('provideCount', count)
	provide('provideArray', array)
</script>
<script setup>
	const count = inject('provideCount', 0);
	const array = inject('provideArray');
</script>



✅ 플러그인

unplugin-auto-import

  • 모든 컴포넌트에서 메서드를 import 하지 않아도 사용 가능
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [ ..., AutoImport({ imports: ['vue'] })],
  ...





📌 출처

수코딩(https://www.sucoding.kr)

profile
프론트엔드를 공부하고 있는 학생입니다🐌

0개의 댓글

관련 채용 정보