럿고의 개발 노트
[Goorm] Vue.js로 시작하는 SPA개발 Chapter6. Components 본문
[Goorm] Vue.js로 시작하는 SPA개발 Chapter6. Components
KimSeYun 2019. 11. 28. 19:07[Goorm] Vue.js로 시작하는 SPA개발
6. Components
6.1. Components 기본 개념
● Components
- Root Vue Instance안에서 Component 체계를 가지고 있는 것
- Vue Instance이기 때문에 Instance Option들을 똑같이 받음
- 사용 순서
■ 웹페이지에서 사용하게 될 Component들을 먼저 정의 및 등록 - JavaScript
■ 웹페에지에서 Component 사용할 곳을 지정 - HTML
■ Root Instance를 생성 - !JavaScript
- Component의 핵심은 재 사용성
6.2. Components 기본 예제 실습
● 실습 코드
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>[Groom]Vue.js로 시작하는 SPA개발 - Chapter06 - Ex1</title> | |
<!-- Vue.js 추가 --> | |
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
</head> | |
<body> | |
<div id="app"> | |
<!-- 컴포넌트의 특징은 똑같은 컴포넌트가 여러개 있어도 각각 인식하는것은 다름 | |
(여기서는 버튼 클릭 횟수가 각 버튼만큼 횟수만 나옴.) --> | |
<button-counter></button-counter> | |
<button-counter></button-counter> | |
<button-counter></button-counter> | |
</div> | |
<script> | |
Vue.component("button-counter", { // 컴포넌트 생성 | |
template: `<button v-on:click="buttonClicked">You Clicked me {{ counter}} times!</button>`, | |
data: function() { // 데이터를 만들어 줌 | |
return { | |
counter:0 // cunter의 값은 0 | |
} | |
}, | |
methods: { | |
buttonClicked(){ // 버튼이 클릭되었을때 실행되는 메소드 | |
this.counter++; // counter에 1씩 더해라 | |
} | |
} | |
}) | |
let vm=new Vue({ | |
el: "#app" | |
}); | |
</script> | |
</body> | |
</html> |
6.3. Props로 Data 주고 받기
● Props
- 사용자 정의 Attribute로, 부모에서 자식 Component로 특정 값을 넘길 때 사용
- Component에서 사용할 Props을 정의해야 함
■ 이후엔 일반 Vue Component의 변수처럼 사용 가능
■ 동일한 Component들을 여러 개의 Instance로 만들어야 할 때 유용
[Component를 안 쓴 v-for]
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>[Groom]Vue.js로 시작하는 SPA개발 - Chapter06 - Ex2</title> | |
<!-- Vue.js 추가 --> | |
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
</head> | |
<body> | |
<!-- Component를 안 쓴 v-for --> | |
<div id="app"> | |
<div v-for="post in posts" :key="post.idx"> <!-- v-for 사용, key값 설정--> | |
<h3>{{ post.title }}</h3> | |
<p>{{ post.description }}</p> | |
</div> | |
</div> | |
<script> | |
let vm = new Vue({ // Vue 생성 | |
el: "#app", | |
data: { | |
posts: [ // posts라는 배열 생성 | |
{ | |
idx: 1, | |
title: "Blog Post 1", | |
description: "Lorem Inpum 1" | |
}, | |
{ | |
idx: 2, | |
title: "Blog Post 2", | |
description: "Lorem Inpum 2" | |
}, | |
{ | |
idx: 3, | |
title: "Blog Post 3", | |
description: "Lorem Inpum 3" | |
} | |
] | |
} | |
}); | |
</script> | |
</body> | |
</html> |
[Component를 쓴 v-for]
6.4. Event로 Data 주고받기
● Events in Components
- v-on & $emit(EVENT_NAME[, ...args])를 이용해 자식과 부모의 데이터 교환 가능
- Custom Event를 정의해서 활용 그낭
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>[Groom]Vue.js로 시작하는 SPA개발 - Chapter06 - Ex4</title> | |
<!-- Vue.js 추가 --> | |
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
</head> | |
<body> | |
<div id="app"> | |
<p v-if="isClicked">Post #{{ clickedPostId}} has been clicked!</p> <!-- 클릭했을때만 뜨게 함--> | |
<div v-for="post in posts" :key="post.idx"> | |
<blog-item v-bind:post="post" v-on:button-clicked="itemClicked"></blog-item> | |
</div> | |
</div> | |
<script> | |
Vue.component("blog-item", { // 컴포넌트 생성 | |
template:'<div v-on:click="itemClicked"> <h3>{{ post.title }}</h3> <p>{{ post.description }}</p></div>', | |
props:["post"], | |
methods: { | |
itemClicked() { // 메소드 생성 | |
this.$emit("button-clicked", this.post.id) // button-clicked라는 이벤트에 값 보내기 | |
} | |
}, | |
}); | |
let vm = new Vue({ | |
el: "#app", | |
data: { | |
posts: [ | |
{ | |
id: 1, | |
title: "Blog Post 1", | |
description: "Lorem Inpum 1" | |
}, | |
{ | |
id: 2, | |
title: "Blog Post 2", | |
description: "Lorem Inpum 2" | |
}, | |
{ | |
id: 3, | |
title: "Blog Post 3", | |
description: "Lorem Inpum 3" | |
} | |
], | |
isClicked:false, | |
clickedPostId:0 | |
}, | |
methods:{ | |
itemClicked(id){ | |
this.isClicked=true; // 버튼클릭하면 true | |
this.clickedPostId=id; // 클릭한 번호(id) | |
} | |
} | |
}); | |
</script> | |
</body> | |
</html> |
6.5. Dynamic Component 개념
● Dynamic Component
- Component는 하나의 Root Element만 가질 수 있음
■ 하나의 <div>안에서 Template을 정의하는 것을 추천
- 일부 Element들 안에서 Component를 사용할 수 없음
■ is Attribute를 활용해서 이를 대체할 수 있음
- 일반적인 Event Bubbling과는 달리, Event는 한 단계만 넘어감
■ 필요시엔 Event를 계속 넘겨주는 것이 필요
■ 복잡한 데이터를 빈번하게 주고받아야 한다면 State를 활용하는 것을 추천
★ Event Bubbling : 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미
6.6. Dynamic Component 실습
● 실습 코드
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>[Groom]Vue.js로 시작하는 SPA개발 - Chapter06 - Ex5</title> | |
<!-- Vue.js 추가 --> | |
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | |
<style> | |
.tab-button{ | |
padding:6px 10px; | |
border-top-left-radius: 3px; /* border-radius : 테두리를 둥글게 만드는 속성 */ | |
border-top-right-radius: 3px; | |
border: 1px solid #ccc; | |
cursor: pointer; | |
background: #f0f0f0; | |
margin-bottom: -1px; | |
margin-right: -1px; | |
} | |
.tab-button:hover { background: #e0e0e0; } /* 링크에 마우스 포인터를 올려 놓았을 때 */ | |
.tab-button:active { background: #e0e0e0; } /* 링크를 마우스로 클릭한 순간 */ | |
.tab{ border: 1px solid #ccc; padding: 10px; } | |
</style> | |
</head> | |
<body> | |
<div id="app"> | |
<button v-for="tab in tabs" v-bind:key="tab" v-bind:class="['tab-button', {active: currentTab == tab}]" v-on:click="currentTab = tab">{{ tab }}</button> | |
<!-- v-bind:class="{클래스명: 조건}" --> | |
<component v-bind:is="currentTabComponent" class="tab" :posts="posts" :post="posts[clickedPostNo]" v-on:post-clicked="postClicked"></component> | |
</div> | |
<script> | |
Vue.component("blog-post",{ | |
template: `<div v-on:click="$emit('post-clicked', post.id);"> | |
<h3>{{ post.title}}</h3> | |
<p>{{ post.description}}</p> | |
</div>`, | |
props:["post"] | |
}); | |
Vue.component("blog-list", { | |
template:`<div> | |
<blog-post v-for="post in posts" :key="post.id" :post="post" v-on:post-clicked="bubbleUpEvent"></blog-post></div>`, | |
props:["posts"], | |
methods:{ | |
bubbleUpEvent(id){ | |
this.$emit('post-clicked', id); | |
} | |
} | |
}); | |
Vue.component("blog-read", { | |
template:`<div> | |
<h1>{{ post.title}}</h1> | |
<p>{{ post.description}}</p> | |
</div>`, | |
props: ["post"] | |
}) | |
Vue.component("blog-about", { | |
template:`<div> | |
<h3>My Blog</h3> | |
<p>My Awsome Blog!</p> | |
</div>` | |
}) | |
let vm = new Vue({ | |
el: "#app", | |
data: { | |
posts: [ | |
{ | |
id: 0, | |
title: "Blog Post 1", | |
description: "Lorem Inpum 1" | |
}, | |
{ | |
id: 1, | |
title: "Blog Post 2", | |
description: "Lorem Inpum 2" | |
}, | |
{ | |
id: 2, | |
title: "Blog Post 3", | |
description: "Lorem Inpum 3" | |
} | |
], | |
Clicked:false, | |
clickedPostNo:0, | |
tabs:["List", "Read", "About"], | |
currentTab: "List" | |
}, | |
methods:{ | |
postClicked(id){ | |
this.currentTab=this.tabs[1]; | |
this.clickedPostNo=id; | |
} | |
}, | |
created(){ | |
this.currentTab=this.tabs[this.clickedPostNo]; | |
}, | |
computed: { | |
currentTabComponent: function(){ | |
return "blog-"+this.currentTab.toLowerCase(); // toLowerCase() : 문자열을 소문자로 변환해서 반환 | |
} | |
} | |
}); | |
</script> | |
</body> | |
</html> |
● 실습 코드 및 출처
- 실습 코드 : https://github.com/ksy90101/Vue.js/tree/master/%5BGoorm%5DVue.js/Chapter06
'Vue.js Note > [Goorm] Vue.js로 시작하는 SPA 개발(동영상강의)' 카테고리의 다른 글
[Goorm] Vue.js로 시작하는 SPA개발 Chapter7. 마무리 (0) | 2019.11.28 |
---|---|
[Goorm] Vue.js로 시작하는 SPA개발 Chapter5. Directives (0) | 2019.11.28 |
[Goorm] Vue.js로 시작하는 SPA개발 Chapter4. Template Syntac (0) | 2019.11.28 |
[Goorm] Vue.js로 시작하는 SPA개발 Chapter3. Vue Instance와 작동원리 (0) | 2019.11.28 |
[Goorm] Vue.js로 시작하는 SPA개발 Chapter2. Hello World로 만나는 Vue (0) | 2019.11.28 |