동일한 데이터가 동일한 페이지에서 여러번 출력되는 경우,
이를 공통된 부모 컴포넌트에서 한방에 관리
props
: 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는데 사용되는 속성
=> 부모는 자식에게 데이터를 전달하며(pass props),
자식은 자신에게 일어난 일을 부모에게 알림(emit event)
모든 props는 자식 속성과 부모 속성 사이에 하향식 단방향 바인딩을 형성!
부모 속성이 업데이트 되면, 자식으로 흐르지만 그 반대는 불가
= 자식 컴포넌트 내부에서 props 변경 불가능!
= 부모 컴포넌트가 업데이트 될 때마다 자식 컴포넌트의 모든 props가 최신 값으로 업데이트 됨
why?
하위 컴포넌트가 부모를 업데이트 해서 데이터 흐름이 복잡해지는 것 방지
Props Name Casing
- camelCase
: 자식 컴포넌트에서 선언할 때
: 템플릿에서 참조해서 사용할 때
-kebab-case
: 부모 컴포넌트에서 자식 컴포넌트로 전달할 때
(camelCase도 가능하지만, HTML 속성 표기법과 동일하게 kebab-case로 표기할 것을 권장)
Static Props & Dynamic Props
: 기본적으로 정적 props를 사용
: but, 자식에서 손자 컴포넌트로 props 해주는 것처럼 원하면 v-bind를 사용하여 동적으로 할당된 props를 사용할 수 있다
```html
<!-- Parent.vue -->
<script>
import {ref} from 'vue'
const name = ref('Alice')
</script>
<template>
<ParentChild my-msg="message" :dynamic-props="name" />
<!-- dynamic-props : props 이름 / name : 동적으로 보낸 props 값-->
</template>
1.부모 컴포넌트에선 prop를 보내주고,
2.자식 컴포넌트에서 사용하기 위해선 선언(defineProp
)해주어야 함
<!--Parent.vue-->
<template>
<div>
<ParentChild my-msg="message"/>
<!-- my-msg: prop 이름 / "message": 값 -->
</div>
</template>
1) 문자열 배열을 사용한 선언
<!--ParentChild.vue-->
<script setup>
defineProps(['myMsg'])
</script>
2) 객체를 사용한 선언 (권장)
<!-- ParentChild.vue -->
<script setup>
defineProps({
// 객체의 키 값(myMsg) : 부모로부터 받은 props의 이름
// 객체의 value 값 : 데이터 타입에 해당하는 생성자 함수(String, Number, Object..)
myMsg: String
})
</script>
객체 선언 문법을 권장하는 이유
: 타입 지정을 통해
- 가독성 향상
- 개발자 실수 미리 방지 (콘솔 경고)
- 유효성 검사 가능
<!-- ParentChile.vue -->
<div>
<p>{{myMsg}}</p>
</div>
<script setup>
const props = defineProps({myMsg:String})
console.log(props) // {myMsg:'message'}
console.log(props.myMsg) // 'message'
</script>
: 자식 컴포넌트가 이벤트를 발생시켜 부모 컴포넌트로 데이터를 전달하는 역할의 메서드
: $
= vue 인스턴스나 컴포넌트 내에서 제공되는 전역 속성이나 메서드를 식별하기 위한 접두어
$emit(event,...args)
<button @click="$emit('someEvent')">클릭</button>
v-on
을 사용하여 수신<ParentComp @some-event="someCallback"/>
<!-- ParentComp라는 자식 컴포넌트로부터 someEvent가 호출되면
부모 컴포넌트에서 선언한 someCallback 함수를 실행하겠다 -->
'$emit'
사용<!-- ParentChild.vue -->
<button @click="$emit('someEvent')">클릭</button>
v-on
을 사용하여 발신된 이벤트를 수신<!-- Parent.vue -->
<template>
<ParentChild @some-event="someCallback" />
</template>
<script>
const someCallback = function() {
// ParentChild에서 emit을 보냈을 때 실행할 로직 작성
}
</script>
'defineEmits()'
사용defineEmits()
을 사용하여 명시적으로 발신할 이벤트를 선언할 수 있음<script>
에서 $emit
메서드를 접근할 수 없기 때문에, defineEmits()
는 $emit
대신 사용할 수 있는 동등한 함수를 반환<!-- ParentChild -->
<script>
// emit이라는 변수에 emit 사용자 정의 이벤트를 할당
const emit = defineEmits(['someEvent','myFocus'])
// 버튼 클릭 시 사용할 이벤트 함수 생성
const buttonClick = function(){
// buttonClick 함수가 실행되면 'someEvent'라는 emit을 실행해라
emit('someEvent')
// emit시 추가인자도 같이 전달해서 보낼 수 있다
emit('someEvent',1,2,3) //추가 인자 = 1,2,3
}
</script>
<template>
<button @click="buttonClick">클릭</button>
</template>
<!-- Parent.vue -->
<template>
<ParentChild @some-event="someCallback" @emit-args="getNumbers">
</template>
<script>
const getNumbers = function(...args){
console.log(args)
// [1,2,3]
console.log(`ParentChild가 전달한 추가 인자 ${args}를 수신했어요`)
// ParentChild가 전달한 추가 인자 1,2,3를 수신했어요
}
</script>
camelCase
: 자식 컴포넌트에서 선언 및 발신 시
kebab-case
: 부모 컴포넌트에서 수신 시