본문 바로가기
관리자

Programming-[Frontend]/Vue.js

Vue.js / 기초 / 7. props로 부모 -> 자식 컴포넌트에 데이터 보내기

728x90
반응형

1. 자식컴포넌트에 props 보내기

 

1-1. 기본 페이지 및 컴포넌트 구성

props는 React에서와 마찬가지로 부모 컴포넌트의 데이터(상태값)를 자식 컴포넌트로 내려줄 때 사용한다. 작성하게 될 페이지 구성을 표현해보면 다음과 같다. Home.vue, About.vue 내부에 Header.vue 컴포넌트를 삽입한 형태다. 코드를 아래에서 확인해보자.

 

App.vue

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
  <div id="app">
    <div>App.vue에서 표시하는 정보입니다.</div><br>
    <router-link to="/">Home</router-link>
    <router-link to="/about">     About</router-link>
    <router-view></router-view>
  </div>
</template>
 
<script>
export default {
  name'App'
}
</script>
 
<style scoped>
h3 {
  color: red;
}
</style>
 
cs

 

 

Home.vue (부모 컴포넌트)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
  <div>
    <h1>Welcome to Home</h1>
    <Header />
  </div>
</template>
<script>
import Header from '@/components/layout/Header'
export default {
  components: {
    Header
  }
}
</script>
cs

 

About.vue(부모 컴포넌트)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
  <h1>Welcome to About</h1>
  <Header></Header>
</div>
</template>
 
<script>
import Header from "@/components/layout/Header";
export default {
  name"About",
  components: {Header}
}
</script>
cs

 

Header.vue (자식 컴포넌트)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
  <div>
  <div class="title">{{ title }}</div>
  <button @click = "updateTitle">update title</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      title : 'Vue.js study~'
    }
  },
  methods: {
    updateTitle() {
      this.title = "Title updated!"
    }
  }
}
</script>
<style scoped>
  .title {
    font-size: 32px;
    color : rgb(37, 37, 158);
  }
</style>
cs

 

 

1-2. props로 data 전달하기

부모 컴포넌트(Home, About) 에서 자식 컴포넌트(Header)로 props를 전달해보자.

 

부모 컴포넌트에서 자식 컴포넌트의 속성 지정

Home과 About 컴포넌트에서 전달할 data값, title을 추가하자. 그리고 title을 Header 컴포넌트를 호출할 때 속성값으로 지정해준다. title 속성을 title data 값으로 지정해주어야 하므로 v-bind의 약어인 콜론(:)을 사용해주었다.

 

About 컴포넌트

Home 컴포넌트에도 title : "Title from home" 이라고 만들어주자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
  <div>
    <h1>About page</h1>
    <Header :title = "title"/>
  </div>
</template>
<script>
import Header from '@/components/layout/Header';
 
export default {
  data() {
    return {
      title : "Title from about"
    }
  },
  components: {
    Header
  }  
}
</script>
cs

 

 

자식컴포넌트에서 부모로부터 받아올 props 설정

Header 컴포넌트의 export default내 props 속성을 추가한다. props 값은 배열로, 14번 줄과 같이 부모로부터 받아오는 속성의 이름인 title을 지정해준다. 그리고 표시를 위해 3번줄과 같이 title을 template에 표기해주면, 아래 영상과 같이 props 값을 잘 받아오는 것을 확인할 수 있다.

 

11번 줄에서 기존 data 속성인 title은 주석처리 해주었는데, props의 title과 중복되기 때문이다. data의 속성값과 props의 속성값이 중복되면 안되는 것을 기억하자. 그리고 아래와 같이 data() 함수가 있다면, 반드시 return{}문을 작성해주어야 한다는 것도 기억하자. 아무것도 return 하지 않더라도, return문 자체는 있어야 한다.

 

Header 컴포넌트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
  <div>
  <div class="title">{{ title }}</div>
  <button @click = "updateTitle">update title</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // title : 'Vue.js study~'
    }
  },
  props : ['title'],
  methods: {
    updateTitle() {
      this.title = "Title updated!"
    }
  }
}
</script>
<style scoped>
  .title {
    font-size: 32px;
    color : rgb(37, 37, 158);
  }
</style>
cs

props를 전달받아 각 페이지를 표기하는 예시, 결과 화면

 

props 직접 변경 금지

props로 지정된 값을 자식 컴포넌트에서 직접 변경하면 안된다. 위 결과화면에서 update title 버튼을 눌러서 updatetitle 메소드를 실행하여 props로 받아오는 title을 변경하는 것을 볼 수 있는데, 작동은 잘 되지만 콘솔창에는 아래와 같은 에러메시지가 뜨게 된다.

 

자식컴포넌트에서 props의 값을 직접 변경했을 때 나타나는 에러 메시지

이것은 props의 목적이 부모컴포넌트에서 데이터의 변경이 있을 때 그것을 그대로 자식컴포넌트에서 받아와서 변경처리를 해주기 위함인데, 자식 컴포넌트에서 props 값 자체를 바꿔버리면 props를 내려주는 의미가 없어지고, 양 쪽에서 변경되어 짜임새 있는 구조로 작성하기가 힘들기 때문이다. 자식컴포넌트의 변경된 데이터를 부모컴포넌트로 올려주는 방법은 Emit을 이용하는 것인데, 다음 글에서 살펴보도록 하자.

 

 


 

2. props의 속성 설정하기

 

보통은 이전 섹션에서 다룬 것과 같이 props를 배열 형태로 표현하는 것이 아니라, 아래와 같이 객체 형태로 표현하여 props의 기본속성을 활용할 수 있다. type, required, default 속성을 이용할 수 있다.

 

 

Header.vue 컴포넌트의 props 설정

1
2
3
4
5
6
7
props : {
 title : {
   type : String,
   required : true,
   default : "this is default title"
 }
}
cs

 

About.vue 컴포넌트에서 Header에 props를 내려주지 않으면 default값이 지정된다. 그러나 정상적인 경우는 아니므로 콘솔창에 에러가 뜬다.

 

 

Home.vue 컴포넌트에서 Header의 title 값을 String이 아닌 number로 지정하면 표시는 되지만 에러가 뜨게 된다.

 

 


 

3. Provide와 Inject

 

부모-자식 컴포넌트간 계층구조가 복잡하게 얽혀있는 경우에는, props를 여러 번 사용하여 부모 컴포넌트의 데이터를 자식 컴포넌트로 전달해야할 수 있다. 만약, Parent.vue -> Child.vue -> ChildChild.vue인 구조인데, Parent에서 ChildChild로 데이터를 전달해야될 상황이라면 Child 컴포넌트에 props : { ... } 를 설정해주고, ChildChild 컴포넌트에도 props : { ... } 을 작성해주어야한다.

 

그러나, Provide, Inject 속성을 활용한다면 Parent 컴포넌트에서 ChildChild 컴포넌트로 한 번에 데이터를 전달할 수 있다. 아래 예시를 참고하자.

 

Parent.vue의 일부

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
  <ChildChild />
</template>
<script>
  import ChildChild from './ChildChild';
  export default {
    components : {ChildChild},
    data() {
      return {
        items : ['A''B']
      };
    },
    provide() {
      return {
        itemLength: this.items.length
      };
    }
  }
</script>
cs

 

 

 

ChildChild.vue의 일부

1
2
3
4
5
6
export default {
  inject : ['itemLength'],
  mounted() {
    console.log(this.itemLength);
  }
}
cs

 

 

 


 

참조

 

1) [유튜브] 코지코더 - '뷰js 2 기초익히기 시리즈'

www.youtube.com/channel/UCI4tTBupvhMX1aWDSm-HAXw

 

2) [도서] Vue.js 프로젝트 투입 일주일 전 - 고승원 저

728x90
반응형