세션8: 컴포넌트 통신 Component Communication & Reusable
1. 이번 세션 학습
- 컴포넌트로 UI를 구성하는 방법
- 어떻게 컴포넌트끼리 통신하는지,
- 컴포넌트 사이에서 어떻게 데이터를 주고 받는지
- 어떤 접근법이 있고, 어떻게 선택 해야하는지
2. 외부에서 데이터 받아오기
중요!같은 컴포넌트를 여러번 사용할때 매번 다른 데이터로 설정한다는 개념
props property의 약자로 커스텀 html 속성을 의미한다.
props 로 설정한 것을 vue가 인식하게 하려면 받는 component 에서 props 를 추가해주어야한다.
가장 단순하게 받는 방법은 [ ] array 이다.
props: [],
그 다음 모든 커스텀 속성을 추가해준다.
props: [
'name',
'phoneNumber',
'emailAddress'
],
this 키워드로 조작할 수 있다.
vue에서는 kebab-case 로 작성해야하고
props 등의 javascript에서는 camelCase로 작성해야한다.
// App.vue
<friend-contact
name="~"
phone-number="010 123 456"
></fiend-contact>
// javascript
this.phoneNumber = '111 222 333'
표기법보다 중요한것은 작동원리이다.
data() 프로퍼티와 마찬가지로 this.~를 사용해액세스 할수 있다.
props로 받아오는 이름과 동일한 이름을 data(), computed 등에서 사용하면 안된다.
이제 컴포넌트에 대해 마크업과 로직을 한번만 정의하면 다른 컴포넌트나 메인앱에서 다양한 데이터를 가지고 필요한 만큼 사용할 수 있다.
props 는 컴포넌트를 유용하게 만들고 그 기능을 강화하는데에 핵심적인 개념이다.
3. 프로퍼티 작동 방식 및 프로퍼티 변경하기
특징! 일반적으로 프로퍼티는 불변값이다.
props로 받아온 값을 변경하려고 하면 에러가 발생한다.
error Unexpected mutation of "isFavorite" prop vue/no-mutating-props
이유 : vue는 단방향 데이터 플로우라는 개념을 사용하기 때문이다.
부모 컴포넌트에서 넘겨준 데이터를 수정하는것은 단방향 데이터 플로우를 위배하기 때문이다.
데이터를 변경하고자 한다면 아래의 2가지 방법을 쓸 수 잇다.
- 부모 컴포넌트에 변경하고 싶다고 요청한다. ( → 나중에 학습 예정 )
- 초기데이터로 취급하고 자식 컴포넌트에서 직접 변경하는것 ( 부모컴포넌트인 App.vue에는 변경된 데이터가 반영되지 않는다.
2번 방법을 쓰기 위해서 data()에 새로운 property를 추가한다.
data() {
return {
...,
friendIsFavorite: this.isFavorite
}
}
4. 프로퍼티 검증하기
위에서는 props에 Array로 추가를 했었다.
검증을 위해 아래와 같이 데이터 타입을 표시할 수 있다.
props:{
name: String,
phoneNumber: String,
emailAddress: String,
isFavorite: Boolean
}
혹은, Object로 표시하고 Required도 표시할 수 있다.
Required 가 false인 경우 default를 설정할 수 있다.
props:{
name: {
type:String,
required: true
},
phoneNumber: {
type:String,
required: true
},
emailAddress: {
type:String,
required: true
},
isFavorite: {
type:String,
required: false,
default: '0',
validator: function(value) {
return value === '1' || value === '0'
}
},
}
좀 더 자세한 구성을 갖추어 두면 컴포넌트를 사용하는 위치를 찾아갈 수 있고, 빼먹었다고 해도 에러가 나는것은 아니지만, required값이 true 인 값을 넘겨주지 않았다면 필수 프로퍼티인 ‘name’이 빠졌다는 [Vue warn] 에러가 발생하게 된다.
이처럼 개발 도중에 발생한 실수를 더 빨리 찾아내는데에 도움이 된다. 컴포넌트가 동작을 안할 때에도 빠르게 원인을 발견할 수 있다.
5. 지원되는 프로퍼티값
- 문자열 String
- 숫자 Number
- 불리언 Boolean
- 배열 Array
- 객체 Object
- 날짜 Date
- 함수 Function
- 심볼 Symbol
6. 동적 프로퍼티 값 사용하기
다른html 처럼 v-bind:is-favorite 로 값을 바인딩 해줄 수 있다. 생략해서 :is-favorite도 가능!
프로퍼티를 동적 값에 바인딩 할 수 있다
재사용 컴포넌트
7. 커스텀 이벤트 방출 (부모→자식 통신)
자식 컴포넌트의 methods에서 this.$emit(’toggle-favorite’)
부모 컴포넌트에서 @toggle-favorite=”toggleFavoriteStatus”
부모 컴포넌트의 methods 에서 toggleFavoriteStatus(){ ~ 내용 ~}
8. 커스텀 이벤트 정의 및 검증하기
this.$emit 이 아니라 props:{} 와 같은 레벨에서 emits 선언하기
- 협업시에 모든 emit을 일일이 찾아보는게 아니라 emits만 보면 되기 때문에 좋다.
emits: [’toggle-favorite’] 혹은
emits: {
'toggle-vavorite': function(id){
if (id) {
return true;
} else {
console.warn('Id is missing');
return false;
}
}
}
9. 데모: 컴포넌트 추가 및 연결하기
<!--prevent 수식어는 제출할때 페이지가 새로고쳐지는 브라우저 기본 동작을 멈춘다.-->
<form @submit.prevent="submitData">
10. 잠재적인 문제점
- 자식 컴포넌트에서 부모 컴포넌트를 거쳐 다시 자식 컴포넌트로 값을 넘겨줄때 복잡하다.
11. Provide + Inject로 해결하기
provide(제공) inject(삽입)
inject는 상위레벨에서 제공된 것만 삽입할 수 있다. 부모 컴포넌트 혹은 조상 컴포넌트.
provide 와 inject는 부모-자식 관계여야한다. 이웃간에는 제공하고 삽입할 수 없다.
부모 컴포넌트A에서 자식 컴포넌트 B 아래의 손자 컴포넌트 C 에 값을 전달할때
A→B→C로 props 해야했는데 provide, inject를 쓰면 A→C로 바로 값을 전달 해줄수 있다.
// A컴포넌트(부모)
data(){
return {
topics: [
...내용
]
}
}
provide: {
topics: [
...내용
]
}
// C컴포넌트(손자)
inject: ['topics']
하지만 위 케이스는 data에 있는 topics의 내용이 변경 되어도 provide에 있는 topics의 값은 변경되지 않는 문제가 있다. 이 경우 provicde: {} 를 provide(){} 로 변경해서 아래와 같이 쓸 수 있다.
provide(){
return{
topics: this.topics
}
}
12. 함수/메서드에서의 Provide + Inject
커스텀 이벤트에서도 provide, inject는 사용할 수 있지만 구현 방법이 다르다.
// 하위 컴포넌트
@click="**selectTopic**(id)"
...
**inject: ['selectTopic']**
// App.vue 컴포넌트
provide() {
return {
topics: this.topics,
**selectTopic: this.activateTopic,**
};
},
methods: {
activateTopic(topicId) {
...
},
},
13. Provide + Inject vs 프로퍼티 및 커스텀 이벤트
프로퍼티와 커스텀 이벤트를 대체하기 위해 Provide와 Inject를 항상 사용해서는 안된다.
실제 프로퍼티와 커스텀 이벤트가 기본적인 통신 메커니즘이 되어야 한다.
불필요하게 통과해야하는 컴포넌트가 있을때 provide 와 inject를 사용해야한다.
provide와 inject의 남용은 코드를 보기 어렵게 만들고, 어디있는지 일일이 찾을수 밖에 없기 때문이다.
14. 섹션 요약
- props
- parent ⇒ child
- Custom Event $emit
- child ⇒ parent
- 형제간 통신은 없다.
- Provide-Inject
- 부모 컴포넌트에 데이터를 제공한 다음 제공한 데이터를 모든 하위 컴포넌트에 삽입할 수 있다.
- 항상 사용해선 안되고 장거리 통신이 필요한 경우에만 사용한다.
'Frontend > Vue 2' 카테고리의 다른 글
[vue]컴포넌트 자세히 알아보기 (0) | 2023.01.10 |
---|---|
[vue2 - error] Vue packages version mismatch: (0) | 2022.01.31 |
[vue] eslint 가 아닌 prettier 가 적용 될 때 (0) | 2021.12.25 |
[vue] 정리 (최종 업데이트:2021-12-21) (0) | 2021.12.07 |
[Netlify] 서버리스 배포 (0) | 2021.10.22 |