[데브코스/TIL] DAY89 - Vue(5)

Minha Ahn·2025년 1월 8일
0

데브코스

목록 보기
40/42
post-thumbnail

✅ 컴포넌트 속성 정의

1. 사용자 정의 속성

  • 컴포넌트 호출과 함께 속성 정의 ⇒ 원하는 값 전달
  • 기본 자료형 : 문자열(String) 자료형
  • String형이 아닌 다른 데이터 타입으로 전달받고 싶다면
    • v-bind 디렉티브로 바인딩해서 정의 (ex. :age="20")
    • 단 문자열 자료형을 v-bind로 넘겨줄 땐, 반드시 백틱으로 한 번 감싸야 함

호출 방식

<ChildComponent name="Minha" age="20" />
<ChildComponent :name="`Minha`" :age="20" />

속성 받는 방식

  • 2가지 방식
    • props 속성을 배열로 할당
    • props 속성을 객체로 할당 (간단하게 자료형만 지정하거나 더 상세하게 지정 가능)
  • 속성값은 전달받은 속성명 그대로 사용
  • 전달받은 값은 data 속성처럼 사용 가능
  • 부모 컴포넌트가 전달해준 속성을 자식 컴포넌트가 받지 않는다면
    • String형 데이터로 전달한 속성은 자식 컴포넌트의 루트 요소의 속성으로 적용됨
    • 루트 요소가 2개 이상이면 적용되지 않음
  • props 속성
    • type : 속성의 타입 지정 (강제성이 없기 때문에 경고만 띄워짐)
      • String, Number, Array. Object, Boolean, Function, Symbol
    • default : 속성을 받지 못할 때의 기본 값 (값 혹은 함수로 지정)
    • required : 속성 전달의 필수 여부
    • validator : 속성 값의 유효성 검사 (Boolean 반환, 유효하지 않으면 경고 발생)
<script>
  export default {
    props: ['name', 'age']
  }
</script>
<script>
  export default {
    props: {
      name: String,
      age: {
        type: Number, // 여러 타입 지정 가능 => [Number, String]
        default() {
          // 로직이 필요할 때 작성
          return 10
        },
        required: true
      }
    }
  }
</script>

속성 이름 작성 시 유의사항

  • 컴포넌트 속성은 케밥 케이스에 따라 작성 (kebab-case)
  • data 옵션 속성이나, props 옵션 속성에서는 카멜 케이스에 따라 작성 (calmelCase)
    • 컴포넌트 속성명을 케밥 케이스로 작성했어도, 받을 때 카멜 케이스로 받을 수 있음

사용자 정의 속성 기본값

  • 속성 지정만 하고 값을 입력하지 않으면 자동으로 true(Boolean)로 값이 정해짐
  • 자식 컴포넌트에서 특정 속성을 Boolean으로 처리 & 부모가 속성 지정을 하지 않으면 false로 처리

2. 사용자 정의 이벤트

  • 컴포넌트에 함수를 전달하는 방법 2가지
    • props로 전달
    • 사용자 정의 이벤트로 전달
  • v-on 디렉티브로 특정 이벤트 타입에 해당하는 이벤트 연결 가능
    • 컴포넌트에 전달하는 것이기 때문에 Web API에 정의된 이벤트 이상으로 전달 가능
    • 이벤트 타입은 사용자가 직접 지정
    • 이벤트 핸들러도 당연히 사용자가 직접 지정

호출 방식

<script>
  // import ~
  export default {
    components: {
      ChildComponent,
    },
    data() {
      return { };
    },
    methods: {
      printHello() {
        console.log('Hello');
      },
    },
  };
</script>
<template>
	<ChildComponent @print-hello="printHello" />
</template>

함수 받는 방식

  • props로 전달 : props 옵션 객체에 할당
  • 이벤트로 전달 : emits 옵션에 할당 (꼭 하지 않아도 되나, 하기를 권장)
    • 배열 할당, 객체 할당 가능
    • 객체 할당의 경우 유효성 검증이 필요할 때 사용
// emits 옵션 - 배열로 할당
export default {
	emits: ['printHello'],
};
// emits 옵션 - 객체로 할당
export default {
  emits: {
    printHello: null;
    printHello() {
  	// 검증 로직
  },
};

함수 사용 방식

  • $emit() 내장 메서드를 이용해 함수 사용
  • 인라인 핸들러 방식
    • <button @onClick="$emit('printHello')">클릭</button>
  • 메서드 핸들러 방식
    • methods 옵션 객체에서 this.$emit('printHello') 사용하는 메서드 정의
    • 새롭게 만든 메서드를 이벤트 핸들러로 지정
  • 인자 전달은 $emit() 내장 메서드의 2번째부터 인자로 전달
    • ex) $emit('printHello', value1, value2)



✅ provide와 inject

  • props drilling을 방지할 수 있는 방법
  • props를 사용하지 않고 데이터를 전달할 수 있는 방법

1. provide

  • 컴포넌트에서 정의한 데이터(함수도 가능)를 하위 컴포넌트에 공유하는 기능
  • provide 옵션 속성 이용
    • 객체 형식 가능 ⇒ data나 computed 활용 불가
    • 함수 형식 가능 ⇒ this 키워드를 통해 data나 computed 활용 가능
provide: {
  message: "Hello",
  name: "Minha",
}
provide() {
  return {
    message: "Hello",
    name: this.name,
    // 함수 형식일 때만 data 속성, computed 속성에 있는 값 사용 가능
  }
}

2. inject

  • 상위 컴포넌트에서 provide 옵션 속성으로 제공하는 데이터를 가져오는 기능
  • inject 옵션 속성 이용
    • 배열 형식 가능
    • 객체 형식 가능 ⇒ 다른 이름으로 받기 가능
  • 하위 컴포넌트의 provide는 inject로 받을 수 없음
    • 상위 컴포넌트가 먼저 렌더링 → 하위 컴포넌트 렌더링
    • 하위 컴포넌트가 렌더링 되기 전에 상위 컴포넌트가 렌더링되어 참조 시도 ⇒ 실패
inject: ['message', 'name'],
inject: {
  newKey: {
    from: 'message', // 다른 이름으로 받기 가능
    default: 40, // 기본값 설정
  },
},

3. 반응형

🔍 반응형이란?
데이터 변경에 따라 UI를 자동으로 업데이트하는 메커니즘

  • Vue는 데이터와 DOM 간의 연동을 자동으로 처리됨
    • data : 객체에 정의된 모든 속성은 기본적으로 반응형
    • computed : 의존하는 데이터가 변경될 때만 다시 계산 (캐싱)
    • watch : 특정 데이터가 변경될 때 실행
  • 데이터가 변경되면 이를 감지하고 UI를 다시 렌더링
  • 궁금) props도 반응형으로 동작?
    • props : 부모 컴포넌트에서 반응형이면 자식 컴포넌트에서도 반응형
  • 궁금) 반응형으로 동작하지 않는 건 어떤 것?
    • 데이터가 변경되어도 이를 감지하지 못하고 UI 업데이트 발생 X
    • 데이터가 변경되고 있긴 함

provide와 inject에서의 반응형

  • provide에 데이터를 일반 객체로 제공하면 반응형으로 동작하지 않음
  • 데이터를 computed로 감싸야 inject로 받는 곳에서 반응형으로 동작
provide() {
  return {
    value: computed(() => this.value)
  }
}

4. Symbol 활용

  • 여러 상위 컴포넌트에서 동일한 이름으로 데이터를 제공하고 있다면?
    • 가장 가까운 컴포넌트의 값을 받아옴
  • 그런 일이 없도록 하려면?
    • Symbol 활용
    • js 파일 하나 만들어서 고유한 키값을 Symbol로 만들고 모아두기
    • Symbol을 키로 하여 provide 객체에 데이터 정의
    • inject는 객체로 정의하여 사용하고 싶은 키로 변경
export const key = Symbol();
export const func = Symbol();
// key랑 func import 하기
provide() {
  return {
    [key]: computed(() => this.value),
    [func]: this.func
  }
}
// key랑 func import 하기
inject: {
  // Symbol 활용 시, 반드리 객체 형태로
  newKey: { from: key },
  fn: { from: func },
}



✅ 컴포넌트 참조

자식 컴포넌트가 부모 컴포넌트로 값을 전달할 방법은 없음
그러나 부모 컴포넌트가 자식 컴포넌트의 값을 참조할 방법은 있음


1. 자식 컴포넌트 참조

  • 자식 컴포넌트 호출 시, ref 속성 사용
    • <ChildComponent ref="ref명" />
    • ref 속성으로 등록한 ref명은 $refs 라는 객체에 등록 (ref명 중복 주의)
    • $ref 객체를 통해 자식 컴포넌트의 data, computed, methods 옵션 속성 접근 가능
    • console.log(this.$refs.ref명.data명) / this.$refs.ref명.method명()
    • ref를 통해 접근한 data는 직접 조작도 가능 (computed는 readonly이므로 조작 불가)
  • ref 참조하는 시점은 자식 컴포넌트가 마운트 된 이후여야 함
    • 그 전에 ref를 참조하면 에러가 발생하지는 않으나, 자식 컴포넌트와 미연결 상태
  • 그러나 자식 컴포넌트의 데이터에 직접 접근하거나 조작하는 건 권장하지 않음

2. 부모 컴포넌트 참조

  • $parent 객체를 통해 부모 컴포넌트 접근 가능 (따로 설정 필요 X)
    • 자식 컴포넌트와 내용 동일 (접근 가능, 직접 조작 가능, 함수 호출 가능)
    • console.log(this.$parent.data명)
  • 역시나 권장하지 않음





📌 출처

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

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

0개의 댓글

관련 채용 정보