4 컴포넌트
source: categories/study/vue-beginner-lv1/vue-beginner4.md
4.1 컴포넌트 소개
이번 시간엔 vue.js 컴포넌트에 대해 알아보겠습니다.
제가 초반부에 말씀드렸던 vue.js특징 중에 components라는 특징이 있습니다. 요즘 대부분의 모던 프론트엔드 프레임워크는 전부 다 components 기반으로 개발을 하고 있습니다.
컴포넌트의 구체적인 내용들을 알아보기 전에 간단하게 살펴보시면,
컴포넌트는 화면의 영역을 구분하여 개발할 수 있는 뷰의 기능입니다.
컴포넌트 기반으로 화면을 개발하게되면 코드의 재사용성이 올라가고 빠르게 화면을 제작할 수 있습니다.
화면의 영역을 영역별로 구분해서 코드로 관리하는 것이 바로 components라고 보시면 됩니다.
위 영역에서 위쪽에 있는 것은 header라고 볼 수 있고, 왼쪽 아래 영역은 contents, 오른쪽은 aside 같은게 되겠죠.
이런 영역별로 components화 할 수 있고 그런 components별로 코드를 관리하는 핵심은
바로 재사용성입니다.
재사용성이란 코드의 반복을 최대한 줄이고 기존에 써놨던 코드를 가지고 최대한 많은 화면을 뽑아내는 것이 component의 핵심이라고 볼 수 있습니다.
component는 영역을 구분해 개발했을 때, 위의 오른쪽 이미지처럼 component간에 관계가 생기게됩니다.
4.2 실습 안내 - 컴포넌트 등록 및 실습
playground/component.html
파일을 생성해보겠습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app'
})
</script>
</body>
</html>
new Vue();
로 인스턴스를 생성하면 그건 기본적으로 Root
컴포넌트가 됩니다.
Root
컴포넌트에 다른 컴포넌트들을 등록해보도록 하겠습니다.
컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()
라는 전역 컴포넌트를 등록하는 방법이 있습니다.
위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면 됩니다.
위와 같은 방식으로 컴포넌트를 등록해나갈 수 있습니다.
일단 app-header
란 컴포넌트를 만들어보겠습니다.
그리고 두번째 인자에 template
속성을 추가하고 헤딩 태그 값을 할당합니다.
위와 같이하시면 컴포넌트가 등록됩니다. 이렇게 등록되었을 때 app-header
라고하는 태그를 만들어주셔야합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
new Vue({
el: '#app'
})
</script>
</body>
</html>
위와 같이 app-header
태그를 넣으시면 아래 script에서 생성한 app-header
컴포넌트를 활용할 수 있습니다.
위와 같이 페이지에서도 Header
가 출력되는 것을 볼 수 있다.
그리고 자연스럽게 Root
라고하는 인스턴스, 컴포넌트 안에 app-header
컴포넌트가 등록이 되었습니다.
위와 같이 실습삼아 app-content
컴포넌트를 만들어보세요.
마찬가지로 template
속성을 쓰시고 <div>content</div>
코드를 직접 등록해보시고 위와 같이 잘 출력되는지 확인해보십시오.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app'
})
</script>
</body>
</html>
4.3 실습 풀이 - 전역 컴포넌트 등록
Root
는 상위(부모) 컴포넌트, app-header
와 app-content
는 하위(자식) 컴포넌트로써 서로 관계를 맺고있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app'
})
</script>
</body>
</html>
Vue.component()
방식은 전역컴포넌트 등록방식입니다.
실제 서비스를 만드실 땐 전역 컴포넌트로 만드실 일이 거의 없을겁니다.
이 다음 시간부터 지역 컴포넌트에 대해 살펴보겠습니다.
4.4 지역 컴포넌트 등록
이번 시간엔 지역 컴포넌트 등록방법, 즉, 서비스를 만드실 때 가장 많이 쓰시는 컴포넌트 등록 방식에 대해서 알아보겠습니다.
앞시간에서 써봤던 전역 컴포넌트 등록 방법은 눈에 익으실 거 같습니다.
하지만 앞으로는 위와 같이 new Vue()
안에 components
속성을 활용해주세요.
위와 같이 components
라는 속성을 정의했는데, 여기에 {}
객체 리터럴을 활용해서
위와 같이 '키': '값'
형태로 정의합니다.
이를 활용해 위와 같이 전역 컴포넌트 등록하듯이 '컴포넌트 이름': 컴포넌트 내용
이렇게 등록합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
}
})
</script>
</body>
</html>
전역 컴포넌트의 구조와 똑같죠? 전역 컴포넌트의 선언 구조와 지역 컴포넌트의 선언 구조는 같습니다.
- 컴포넌트 이름: 컴포넌트 태그라고 보통 표현을 하는데, 여튼 컴포넌트 태그를 정의하고
- 컴포넌트 내용: 컴포넌트 태그에 실제로 들어가는 내용 정의
위와 같이 app-footer
컴포넌트를 만들어봤습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
<app-footer></app-footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
</script>
</body>
</html>
이렇게 다 등록된걸 볼 수 있다.
4.5 전역 컴포넌트와 지역 컴포넌트의 차이점
전역 컴포넌트
지역 컴포넌트
주의할점: components
!라는 것. 뒤에 s
가 붙는다.
컴포넌트 하나만 만들거 아니잖아? 여러개 만들거니깐 component
가 아니라 components
!
나중에 라우터를 배우실 때는 라우터의 속성엔 component
이렇게 사용할 것이다.
그런데 보통은 컴포넌트를 등록할 때 여러개를 등록하기 때문에 s
가 붙습니다.
마찬가지로 method
도 method
가 아니라 methods
라고 해야됩니다.
보통은 서비스를 구혈할 때 로직이 한개가 아니라 여러개이기 때문에 그렇습니다.
나중에 싱글 파일 컴포넌트 체계로 갔을 때 위와 같이 해놓으면 특정 컴포넌트 하단에 어떤 컴포넌트가 등록되는지 컴포넌트 속성으로 바로 알 수가 있다.
따라서 서비스를 구현하실 때는 대부분 components
라는 속성을 이용하여 구현한다.
Vue.component()
이거는 나중에 서비스를 구현하실 때, 대부분 플러그인이나 라이브러리 형태로, 전역으로 사용해야되는 컴포넌트만 Vue.component()
로 사용을 합니다.
일반적으로는 위처럼 등록을 해나간다라는 거를 인지하고 계시면 될거 같습니다.
4.6 컴포넌트와 인스턴스와의 관계
컴포넌트와 인스턴스의 관계 살펴보겠습니다.
먼저 컴포넌트를 정의를 하겠습니다.
보시기 쉽게 전역 하나와 지역 하나만 남기겠습니다.
app-header
, app-footer
두개의 컴포넌트만 남겼습니다.
만약에 아래에다 new Vue()
라는 인스턴스를 하나 더 만들었습니다. 인스턴스는 여러개 생성할 수 있습니다.
물론 여러개 생성할 필요는 없지만 지금은 설명이므로 여러개 생성했습니다.
app2
라는 id
를 가진 태그도 하나 더 만듭니다. 이 태그에 인스턴스를 붙일겁니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
<app-footer></app-footer>
</div>
<div id="app2">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
// Vue 인스턴스는 여러개 생성할 수 있습니다.
new Vue({
el: '#app2'
})
</script>
</body>
</html>
위와 같이 el
에 #app2
를 할당하고 화면을 보면,
Root
가 2개가 생겼습니다.
인스턴스를 생성하면 그것이 Root
컴포넌트가 된다라고 말씀드렸었고, 그렇기 때문에 인스턴스를 하나 더 만드니깐 Root
컴포넌트가 하나 더 생겼습니다. ($vm0
, $vm1
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
<app-footer></app-footer>
</div>
<div id="app2">
<app-header></app-header>
<app-footer></app-footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
// Vue 인스턴스는 여러개 생성할 수 있습니다.
new Vue({
el: '#app2'
})
</script>
</body>
</html>
여기서 #app2
요소에 app-header
, app-footer
컴포넌트를 동일하게 넣어보겠습니다.
보시면 app-header
컴포넌트는 뜨는데, app-footer
컴포넌트는 뜨지 않습니다.
콘솔창에 가보시면 app-footer
를 Unknown custom element
라고 얘기를 하면서 did you register the component correctly?
컴포넌트를 제대로 등록했는지 물어봅니다.
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
전역 컴포넌트는 인스턴스를 생성할 때마다 따로 등록할 필요가 없습니다.
위에 보시면 Vue.component()
로 전역 컴포넌트를 등록했죠?
따라서 인스턴스에 따로 생성을 안해도 모든 인스턴스에서 접근이 가능하다고 보시면 됩니다.
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
하지만 지역 컴포넌트 같은 경우에는 인스턴스마다 새로 생성을 해주셔야됩니다. 그래서 똑같은 컴포넌트를 집어넣을 때 지역 컴포넌트화해서 만들면 똑같은걸 계속 만들어서 넣어야되는 번거로움이 있죠.(물론 실무에서 그렇게하진 않겠지만)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, user-scalable=no">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue.component에 등록한 컴포넌트입니다. 아래와 같이 app-header 태그를 만들어줍니다. -->
<app-header></app-header>
<app-content></app-content>
<app-footer></app-footer>
</div>
<div id="app2">
<app-header></app-header>
<app-footer></app-footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 컴포넌트를 등록하는 가장 간단한 방법은 Vue.component()라는 전역 컴포넌트를 등록하는 방법입니다.
// Vue.component('컴포넌트 이름', '컴포넌트 내용');
// 위와 같이 첫번째 인자엔 컴포넌트 이름, 두번째 인자엔 컴포넌트 내용을 넣으면됩니다.
// app-header란 컴포넌트를 만들어보겠습니다.
// 두번째 인자에 template 속성을 추가하고 해딩 태그 값을 할당합니다.
Vue.component('app-header', {
template: '<h1>Header</h1>'
})
Vue.component('app-content', {
template: '<div>content</div>'
})
new Vue({
el: '#app',
// 지역 컴포넌트 등록은 이렇게 vue 인스턴스의 components 속성을 활용합니다.
// components: {
// '컴포넌트이름': '컴포넌트내용'
// }
components: {
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
// Vue 인스턴스는 여러개 생성할 수 있습니다.
new Vue({
el: '#app2',
components: {
// app-footer 컴포넌트를 이 Vue 인스턴스에도 생성해줍니다.
'app-footer': {
template: '<footer>footer</footer>'
}
}
})
</script>
</body>
</html>
아무튼 위와 같이 app-footer
컴포넌트를 또 생성을 해줘야지
화면에서 이상없이 나타나게됩니다.
인스턴스를 생성할 때마다 컴포넌트를 등록해줘야하는 것이 바로 지역 컴포넌트이다.
위와 같이 전역 컴포넌트로 등록하시면 인스턴스를 생성할 때마다 등록하실 필요가 없습니다.
하지만 여튼 서비스를 실제 구현하실 땐, 대부분 인스턴스 하나를 생성하고 그 안에 지역 컴포넌트를 붙여나가는 형식으로 진행하기 때문에, 전역 컴포넌트는 잘 안쓴다는 것!