럿고의 개발 노트

[Goorm] Vue.js로 시작하는 SPA개발 Chapter6. Components 본문

Vue.js Note/[Goorm] Vue.js로 시작하는 SPA 개발(동영상강의)

[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>
view raw VueEx1.html hosted with ❤ by GitHub


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>
view raw VueEx1.html hosted with ❤ by GitHub

[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>
view raw VueEx1.html hosted with ❤ by GitHub


6.5. Dynamic Component 개념


● Dynamic Component


- Component는 하나의 Root Element만 가질 수 있음

■ 하나의 <div>안에서 Template을 정의하는 것을 추천

- 일부 Element들 안에서 Component를 사용할 수 없음

 is Attribute를 활용해서 이를 대체할 수 있음

- 일반적인 Event Bubbling과는 달리, Event는 한 단계만 넘어감

 필요시엔 Event를 계속 넘겨주는 것이 필요

 복잡한 데이터를 빈번하게 주고받아야 한다면 State를 활용하는 것을 추천


★ Event Bubbling : 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미

- 출처 : https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/#%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81---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>
view raw VueEx1.html hosted with ❤ by GitHub




● 실습 코드 및 출처


- 실습 코드 : https://github.com/ksy90101/Vue.js/tree/master/%5BGoorm%5DVue.js/Chapter06

- 출처 : https://edu.goorm.io/learn/lecture/13020/vue-js%EB%A1%9C-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-spa-%EA%B0%9C%EB%B0%9C




Comments