본문 바로가기
Frontend/Vue 2

[vue]컴포넌트 통신

by SOLYI 2023. 1. 2.

세션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가지 방법을 쓸 수 잇다.

  1. 부모 컴포넌트에 변경하고 싶다고 요청한다. ( → 나중에 학습 예정 )
  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
    • 부모 컴포넌트에 데이터를 제공한 다음 제공한 데이터를 모든 하위 컴포넌트에 삽입할 수 있다.
    • 항상 사용해선 안되고 장거리 통신이 필요한 경우에만 사용한다.
반응형