2024. 7. 7. 20:58ㆍFE/Vue.js
1. Props
- Props
: 컴포넌트에 등록할 수 있는 사용자 정의 속성.
: 상위 컴포넌트가 하위 컴포넌트에게 전달하는 값.
가. defineProps()
<!-- BlogPost.vue -->
<script setup>
const props = defineProps(['title'])
console.log(props.title)
</script>
<template>
<h4>{{ title }}</h4>
</template>
defineProps
는 <script setup>
내에서만 사용할 수 있는 compile-time macro다.
defineProps
는 컴포넌트에 전달된 모든 props
를 객체로 반환한다.
defineProps(['title'])
: 부모 컴포넌트로부터 받아올 속성의 이름.
:title
이라는 속성값을 받아와 사용할 수 있다.props.title
: 필요한 경우 JavaScript에서 접근할 수 있다.
defineProps
의 다양한 타입이 인자로 올 수 있다.
위에서는 배열이 인자로 왔다.
// <script setup>에서
defineProps({
title: String,
})
// <script setup>가 아닐 때
export default {
props: {
title: String,
}
}
하지만 객체를 인자로 전달하는 것을 추천한다.
<script setup>
const props = defineProps({
// 기본 타입 체크
// (`null`과 `undefined`는 모든 타입에서 허용됩니다)
propA: Number,
// 여러 타입 허용
propB: [String, Number],
// 문자열 필수
propC: {
type: String,
required: true
},
// 기본 값을 가지는 숫자형
propD: {
type: Number,
default: 100
},
// 기본 값을 가지는 객체
propE: {
type: Object,
// 객체 또는 배열 기본값은 팩토리 함수에서 반환되어야 합니다.
// 함수는 컴포넌트에서 받은 rawProps를 인자로 받습니다.
// (rawProps: 부모 컴포넌트에게 받은 props 전체 객체)
default(rawProps) {
return { message: '안녕!' }
}
},
// 사용자 정의 유효성 검사 함수
// 3.4+ 부터는 모든 props가 두 번째 인수로 전달 됨
propF: {
validator(value, props) {
// 값은 다음 문자열 중 하나와 일치해야 합니다.
return ['성공', '경고', '위험'].includes(value)
}
},
// 기본값이 있는 함수
propG: {
type: Function,
// 기본값 객체나 배열을 정의하는 팩토리 함수가 아니라
// 기본값으로 사용할 함수입니다.
default() {
return 'Default function'
}
}
})
</script>
Props의 이름뿐 아니라 다양한 옵션도 추가할 수 있다.
나. 정적 Props
<BlogPost title="Vue와 함께한 나의 여행" />
다. 동적 Props
<!-- 변수 값을 동적으로 할당 -->
<BlogPost :title="post.title" />
<!-- 복잡한 표현식의 값을 동적으로 할당 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />
라. 주의점
식 컴포넌트 내부에서 props를 변경하려 하면 안 된다.
Props는 읽기 전용입니다!
모든 props는 자식 속성과 부모 속성 사이에 하향식 단방향 바인딩을 형성한다.
부모 property가 업데이트되면 자식도 업데이트되지만 그 반대는 안된다.
앱에서의 데이터 흐름을 이해하기 어렵기 때문에 금지한다.
2. Emit
props
는 부모에서 자식으로 업데이트되는 하향식 단방향 바인딩만 지원한다.
자식 컴포넌트에서 부모 컴포넌트의 property를 수정할 순 없다.
대신에 자식 컴포넌트에서 부모 컴포넌트로 이벤트는 보낼 순 있다.
가. $emit
<!-- 자식 컴포넌트 -->
<template>
<button @click="$emit('updateEvent', '새로운 값')">이벤트 발생</button>
</template>
$emit('eventName', ...args)
: 자식 컴포넌트에서 이벤트를 발생시켜서 부모 컴포넌트로 데이터를 전달하는 메서드
:$
는 Vue에서 제공되는 전역 속성이나 메서드를 식별하기 위한 접두사
나. defineEmits()
<!-- 자식 컴포넌트 -->
<template>
<button @click="emitEvent">이벤트 발생</button>
</template>
<script setup>
const emit = defineEmits(['updateEvent'])
const emitEvent = () => {
emit('updateEvent', '새로운 값')
}
</script>
$emit
대신에 defineEmits()
를 사용하여 명시적으로 발신할 이벤트를 선언할 수 있다.
위의 코드에서 버튼을 누르면 emitEvent
함수가 실행된다.
emitEvent
는 updateEvent
라는 이벤트를 부모 컴포넌트에게 전달한다.
(이벤트 이름은 자유다.)
다. 이벤트 처리
<!-- 부모 컴포넌트 -->
<script setup>
const a = ref("오래된 값");
</script>
<ChildCoponent @updateEvent="(v) => a = v" />
부모 컴포넌트에서는 보내진 이벤트를 받아 처리한다.
<!-- 부모 컴포넌트 -->
<script setup>
const a = ref("오래된 값");
const updateHandler = (v) => {
a = v;
};
</script>
<!-- 또는 이벤트를 처리할 함수를 지정할 수 있다. -->
<ChildComponent @updateEvent="updateHandle" />
이벤트를 처리할 콜백함수를 지정할 수도 있다.
라. Event Name Casing
<!-- 자식 컴포넌트 -->
<button @click="$emit('updateEvent', '새로운 값')">이벤트 발생</button>
<!-- 또는 -->
<script setup>
...
const emit = defineEmits(['updateEvent'])
const emitEvent = () => {
emit('updateEvent', '새로운 값')
}
</script>
자식 컴포넌트에서 이벤트를 선언하고 발신할 때 → camelCase
<ChildComponent @updateEvent="updateHandle" />
<!-- 보다는 -->
<ChildComponent @update-event="updateHandle" />
부모 컴포넌트에서 수신 시 → kebab-case
HTML 속성은 대소문자를 구분하지 않기 때문에 camelCase 표기법을 사용하면 문제가 생길 수 있다.
'FE > Vue.js' 카테고리의 다른 글
[Vue.js] Pinia (0) | 2024.07.07 |
---|---|
[Vue.js] Vue-Router (0) | 2024.07.07 |
[Vue.js] Component (0) | 2024.07.07 |
[Vue.js] Watchers (0) | 2024.07.07 |
[Vue.js] 이벤트 핸들링 (0) | 2024.07.07 |