컴포넌트란?
컴포넌트는 하나의 블록을 의미한다. 컴포넌트를 활용하여 화면을 만들면 보다 빠르게 구조화하여 일괄적인 패턴으로 개발할 수 있다. 화면의 영역을 컴포넌트로 분리함으로써 재사용 편리한 코드가 구조가 되는것이다.
쇼핑몰의 화면을 예를 들어보면, 화면의 header, footer, menu 등을 컴포넌트단위로 분리하여 어느 화면에서나 재사용 할 수 있고, 더 세부적으로 장바구니 버튼 같은 것들을 분리하여 재사용 할 수도 있다.
전역, 지역 컴포넌트
전역 컴포넌트 등록은 Vue.component(tagName, options)를 사용한다.
컴포넌트를 components 인스턴스 옵션으로 등록하여 다른 인스턴스/컴포넌트의 범위에서만 사용할 수있는 지역적인 컴포넌트를 만들 수도 있다.
app.html
<div id="example1">
<p>Example1 : 전역 컴포넌트</p>
<my-template></my-template>
</div>
<div id="example2">
<p>Example2 : 지역 컴포넌트</p>
<localcomp></localcomp>
</div>
<div id="example3">
<p>Example3 : 전역,지역 컴포넌트</p>
<my-template></my-template>
<localcomp></localcomp>
</div>
app.js
Vue.component('my-template', {
template: '<b>전역 컴포넌트입니다!</b>'
})
let example1 = new Vue({
el: '#example1'
})
let LocalComponent = {
template : `<b>지역 컴포넌트입니다!</b>`
}
let example2 = new Vue({
el: '#example2'
, components : {
'localcomp' : LocalComponent
}
})
let example3 = new Vue({
el : '#example3'
})
위의 예제에서 전역 컴포넌트로 등록한 my-template은 example1, example3 div에 나타날 수 있으나, example2 인스턴스에만 components로서 지역적으로 등록된 LocalComponent는 example2 div에서만 나타난다.
결과화면
컴포넌트 작성시 주의할 점 - data는 반드시 함수여야 한다.
Vue 생성자에 사용하는 대부분의 옵션은 컴포넌트에서 사용할 수 있다. 다만, data는 필히 함수여야 한다.
app.html
<div id="example1">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
app.js
let data = {counter : 0}
Vue.component('my-component', {
template : `<button @click="counter += 1">{{counter}}</button>`
, data: function () {
// 이 경우 각 컴포넌트가 동일한 data를 공유하고 있어
// 버튼 클릭시 모든 버튼(data)이 counter된다.
// return data;
// 따라서 각각 새로운 counter 객체를 반환해야 한다.
return {counter : 0};
}
})
new Vue({
el : '#example1'
})
props로 데이터 전달하기
하위컴포넌트의 템플릿에서 상위 컴포넌트의 데이터를 직접 참조할 수 없다. 데이터는 props 옵션을 통해서 하위컴포넌트로 전달되어질 수 있다. (상위->하위)
prop은 상위 컴포넌트의 정보를 전달하기위한 사용자 지정 특성이다. 하위 컴포넌트는 props 옵션을 사용하여 수신 할 것으로 기대되는 props를 명시적으로 선언해야한다.
app.html
<div id="example1">
<h2>example1</h2>
<p>I'm parent!</p>
<child message="(상->하) props를 통한 데이터 전달"></child>
</div>
app.js
/* Ex1. child 컴포넌트의 prop활용 */
new Vue({
el: "#example1"
, components: {
child: {
props: ['message']
, template: '<span>{{ message }}</span>'
}
}
})
'child'라는 이름의 template을 선언하고, <child>를 사용하는 쪽(상위 컴포넌트)에서 message를 전달한 예제이다.
props의 이름 명시법(camelCase와 kebab-case)
HTML속성은 대소문자를 구분하지 않으므로, template에서 사용한 cacelCase의 props이름을 kebab-case로 명시해야 한다.
app.html
<div id="example2">
<h2>example2</h2>
<camel my-message="camelCase vs kebab-case"></camel>
</div>
app.js
/* Ex2. script에서의 camelCase, html에서의 kebab-case */
new Vue({
el: "#example2"
, components: {
camel: {
props: ['myMessage']
, template: '<b>{{ myMessage }}</b>'
}
}
})
동적 props
v-bind를 이용하여 부모의 데이터에 props를 동적으로 바인딩 할 수 있다.
데이터가 상위에서 업데이트 될 때마다 하위 컴포넌트로 전달된다.
app.html
<div id="example3">
<h2>example3</h2>
<input v-model="parentMsg">
<mirror :message="parentMsg"></mirror>
</div>
app.js
/* Ex3. prop 동적 바인딩 */
let model = {
parentMsg: ''
}
new Vue({
el: "#example3"
, data: model
, components: {
mirror: {
props: ['message']
, template: '<b>{{ message }}</b>'
}
}
})
결과화면
input 태그에 값이 입력되면 v-model의 양방향 바인딩 특성으로 해당 모델에 바인딩 되어있는 객체들의 데이터가 같이 변경된다.
mirror 컴포넌트의 message prop은 v-bind(:)로 parentMsg에 바인딩 되어있어 상위 컴포넌트의 데이터를 즉각 화면에 표시한다.
객체의 모든 속성을 props로 전달하기
객체의 모든 속성을 props로 전달하려면, 인자없이 v-bind를 쓸 수 있다. (v-bind:prop-name 대신 v-bind)
app.html
<!-- 객체의 모든 속성을 props로 전달하기 -->
<div id="example4">
<h2>example4</h2>
<todo-item v-bind="todo"></todo-item>
</div>
app.js
/* Ex4. 객체의 모든 속성을 props로 전달하기 */
let todo = {
text: 'study hard'
, isComplete : 'not yet :('
}
new Vue({
el: "#example4"
, data : {
todo: todo
}
, components: {
'todo-item': {
props: ['text', 'isComplete']
, template: '<b>{{text}} , {{isComplete}}</b>'
}
}
})
'Tech > Vue.js' 카테고리의 다른 글
[Vue.js] 이벤트 핸들링 (0) | 2020.07.28 |
---|---|
[Vue.js] 조건문, 반복문, 객체 데이터 추출 (0) | 2020.07.22 |
[Vue.js] Vue 인스턴스 생성. 데이터 입력과 출력 (0) | 2020.07.19 |
댓글