Vue.js 컴포넌트 통신

강정우·2023년 3월 31일
0

vue.js

목록 보기
14/72
post-thumbnail
post-custom-banner

props

  • react와 완전히 동일한 개념이다. props로 부->자 데이터를 넘겨주는 방식이다.

  • 하지만 문법이 조금 다른데 알아보자.

문법 (부->자)

  • 우선 부->자 데이터를 내릴 때 컴포넌트에서 props 즉, 속성값으로 넘기는 방식은 동일하다. 다만, 속성값을 kebab-case로 적어주어야한다.

App.vue

<template>
  <section>
    <ul>
      <friend-contact 
       name="정우" 
       phone-number="010-1234-5678" 
       email-address="정우@google.com"></friend-contact>
    </ul>
  </section>
</template>
  • 그리고 이 속성값을 받은 컴포넌트에서 사용을 하려면 Vue 구성 객체의 속성값으로 props 를 추가해서 배열로 해당 값을 받아온다.

  • 이때 속성값은 항상 문자열이여야하는데 만약 다른 type을 보내고 싶다면 쉽게 binding하면 그만이다. 아래와 같이 바인딩한다면 단순 type지정 뿐만 아니라 간단한 JS 로직도 써 넣을 수 있다. 즉, 동적바인딩이 가능하다.

      <friend-contact
          v-for="friend in friends"
          :key="friend.id"
          :name=friend.name
          :phone-number="friend.phone"
          :email-address="friend.email"
          :is-favor=friend.favor
      ></friend-contact>

custom(friend-contact).vue

<template>
  ...
</template>

<script>
export default {
  props:[
    'name', 'phoneNumber', 'emailAddress'
  ],
  
  ...
  
}
</script>
  1. kebab-case 로 넘겨받은 속성(props)값은 .vue에서 사용될 때 camelCase로 바뀌서어 사용된다.
    • why? => kebab-case 는 유효하지 않은 JS 문법이기 때문에 camelCase 로 작성한다.
    • 이때 Vue는 camelCase로 작성된 프로퍼티를 자동으로 해석해서 kebab-case로 바꿔준다.

대시가 포함된 버전으로 바꿔 줍니다
2. data props나 computed props등 다른 속성값과 이름이 중복되면 안 된다.

  • 그리고 props에 들어있는 값들은 this. 키워드로 참조하여 methods등 다른 속성값에서도 사용가능하다.

문법 (부->자) +

  • 우리가 작업을 하다보면 컴포넌트가 복잡해지거나 팀으로 작업하는 경우에는 프로퍼티에 대한 정보를 더 많이 공유해야 할 수도 있다. 그리서 Vue는 우리가 컴포넌트에 잘못된 데이터를 전달하거나 필요한 프로퍼티를 빼먹었을 때 이를 알려주기 위해 프로퍼티 배열을 다른 것으로 대체할 수 있는데 얘를 들어 TS 처럼 type을 지정하거나
<template>
  ...
</template>

<script>
export default {
  props:{
    name:String,
    phoneNumber:String,
    emailAddress:String,
    isFavor:Boolean
  },
  ...
}
</script>
  • 지정 가능한 type들 : 문자열(String), 숫자(Number), 불리언(Boolean), 배열(Array), 객체(Object), 날짜(Date), 함수(Function), 심볼(Symbol)

  • 또는 객체를 지정하여 type 이외에도 여러 제약을 줄 수 있다.

<script>
export default {
  props:{
  props:{
    name:{
      type:String,
      require:true
    },
    phoneNumber:{
      type:String,
      require:true
    },
    emailAddress:{
      type:String,
      require:true
    },
    isFavor:{
      type:String,
      require: false,
      default:"0",
      validator:function (value) {
        return value==='0'||value==='1'
      }
    }
  },
  },
  ...
}
</script>
  • 예를 들어 require 속성을 줄 수 있고 이는 boolean으로 관리해야한다. 또한 default 속성으로 값이 넘어오지 않았을 때의 기본값을 설정해 둘 수 있다.

  • 또한 validator 속성을 사용하여 특정 값만을 갖도록 지정할 수 있다. 여기서는 type은 String이지만 오직 0,1만을 갖을 수 있도록 만들었다.

  • 조금 더 자세한 것은 공식문서에서도 확인할 수 있다.

property는 불변해야한다.

  • 뭐지? 왜? => Vue는 단방향 데이터 플로우 (Unidirectional data flow)라는 개념을 사용하기 때문이다.

  • 위 사진을 보면 props로 부모에서부터 받아온 값인 "isFavor"를 자식 컴포넌트에서 그냥 변경하려고 하니 ESLint error가 발생하였다.

  • 그러다면 자->부 로 lifting state up은 불가능한 것일까? 2가지 방법이 있다.

1. 부모 컴포넌트에 변경요청하기 (자->부)

문법

  • Vue의 커스텀 컴포넌트가 부모에게 무언가 일어났음을 알리고자 한다면 자식컴포넌트는 부모가 수신할 이벤트를 발생시켜야 한다. 마찬가지로, Vue 컴포넌트 내부에 우리가 지정한 커스텀 이벤트를 발생시킬 수 있다.
toggleFavor(){
	// this.favor = !this.favor
	this.$emit('toggle-favorite', this.id);
}
  • this 키워드 밑에 붙어있는 내장 메서드로써 emit발산하다 라는 뜻을 갖고있다.

emit()

  • 이 메서드는 부모 컴포넌트에서 수신할 수 있는 커스텀 이벤트를 발생시켜 준다.

  • emit는 최소한 하나의 인수인 커스텀 이벤트의 이름을 요구한다.

this.$emit('kebab-case-method-name', 인수);
  • 2번째 인수 사실 메서드이름을 제외하고 뒤에 몇개도 붙어도된다. 그리고 뒤엔 어떤 값일지 확인해주는 식별자가 붙으면 좋다. 그래서 이벤트가 발생할 때 함께 전달되는 것이다.

ps. 이벤트는 kebab-case로 작성하자.

emit() listen

  • 부모 컴포넌트
<friend-contact
	v-for="friend in friends"
	:key="friend.id"
	:name=friend.name
	:phone-number="friend.phone"
	:email-address="friend.email"
	:is-favor=friend.favor
	@toggle-favorite="toggleFavoriteStatus"
></friend-contact>

...

<script>
export default {
	...
    methods:{
    	toggleFavoriteStatus(friendId){
      		const selectedFriendId = this.friends.find(freind => freind.id === friendId);
      		selectedFriendId.favor = !selectedFriendId.favor
    	}
    }
    ...
}
</script>
  • v-on 또는 @ 예약어를 통하여 자식 컴포넌트로부터 이벤트를 속성값으로 listen 해주면 된다.
    그래서 받은 값을 어떻게 처리할 지 지정 methods 로직을 pointing 하고 있으면 된다.

2. props를 자식 컴포넌트의 초기 값으로 설정하여 변경하기

  • 무슨말이냐면 자식 컴포넌트 내부의 초기 데이터로 취급해 자식 컴포넌트에서 직접 변경하는 것이다.
    단, 이땐 부모컴포넌트에는 값이 반영이 안 된다.

example.vue

<template>
	...
    	<h2>{{name}} {{favor ? '즐찾' : ''}}</h2>
    	<button @click="toggleDetails">{{ detailAreVisible ? 'Hide' : 'Show'}} Detail</button>
    	<button @click="toggleFavor">{{ favor ? '삭제' : '추가'}}</button>
    ...
</template>

<script>
export default {
  props:[
    'name', 'phoneNumber', 'emailAddress', 'isFavor'
  ],
  data(){
    return{
      detailAreVisible:false,
      favor : this.isFavor				// yo부분임!
    }
  },
  methods:{
    toggleDetails(){
      this.detailAreVisible = !this.detailAreVisible
    },
    toggleFavor(){
      this.favor = !this.favor
    }
  }
}
</script>
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글