목차
- 컴포넌트가 무엇인가요?
- 컴포넌트 사용법
- 컴포넌트 뼈대 만들기
- 컴포넌트 내용 만들기
- 자식 컴포넌트 만들기
- 부모 자식간 이벤트 연결
- 부모의 데이터가 변경될 때 1
- 부모의 데이터가 변경될 때 2
- 끝으로...
1. 컴포넌트가 무엇인가요?
컴포넌트는 Vue의 가장 강력한 기능 중 하나입니다. 기본 HTML 엘리먼트를 확장하여 재사용 가능한 코드를 캡슐화하는 데 도움이 됩니다. 상위 수준에서 컴포넌트는 Vue의 컴파일러에 의해 동작이 추가된 사용자 지정 엘리먼트입니다. 경우에 따라 특별한 is 속성으로 확장 된 원시 HTML 엘리먼트로 나타날 수도 있습니다.
Vue.component('todo-list', {
template: '<div>Todo List</div>'
});
new Vue({
el: '#root',
template: '<todo-list></todo-list>'
});
2. 컴포넌트 사용법
3. 컴포넌트 뼈대 만들기
<script type="application/javascript">
Vue.component('todo-content', {
template: `
<div style="width: 720px; background: #dddddd; margin: 0 auto;">
<h1>Todo List</h1>
<slot></slot>
</div>`
});
new Vue({
el: '#root',
template: `<todo-content></todo-content>`,
});
</script>
4. 컴포넌트 내용 만들기
<script type="application/javascript">
Vue.component('todo-content', {
template: `
<div class="todo-content">
<h1>Todo List</h1>
<slot></slot>
</div>`
});
Vue.component('todo-list', {
template: `
<ul>
<li>예시값</li>
</ul>`
});
new Vue({
el: '#root',
template: `
<todo-content>
<todo-list></todo-list>
</todo-content>`,
});
</script>
5. 자식 컴포넌트 만들기
Vue.component('todo-content', {
template: `
<div class="todo-content">
<h1>Todo List</h1>
<slot></slot>
</div>`
});
Vue.component('todo-list', {
data() {
return {
items: ['A', 'B', 'C']
}
},
template: `
<ul>
<todo-item
v-for="item in items"
:name="item"
></todo-item>
</ul>`
});
Vue.component('todo-item', {
props: ['name'],
template: `<li>{{name}}</li>`
});
new Vue({
el: '#root',
template: `
<todo-content>
<todo-list></todo-list>
</todo-content>`,
});
6. 부모 자식간 이벤트 연결 - 완료 버튼
Vue.component('todo-list', {
data () {
return {
items: ['A', 'B', 'C']
}
},
methods: {
completed (item) {
const items = this.items;
const i = items.indexOf(item);
items.splice(i, 1);
}
},
template: `
<ul>
<todo-item
v-for="item in items"
:key="item"
:name="item"
v-on:completed="completed"></todo-item>
</ul>`
});
Vue.component('todo-item', {
props: ['name'],
methods: {
complete () {
this.$emit('completed', this.name);
}
},
template: `
<li>
{{name}}
<button class="btn" @click="complete">완료</button>
</li>`
});
7. 부모의 데이터가 변경 될 때 1 - 할일 추가
Vue.component('todo-list', {
data() {
return {
inputItem: '',
items: ['A', 'B', 'C']
}
},
methods: {
completed(item) {
const items = this.items;
const i = items.indexOf(item);
items.splice(i, 1);
},
appendTodoItem() {
this.items.push(this.inputItem);
this.inputItem = '';
}
},
template: `
<div>
<input class="input-text" type="text" v-model="inputItem"/>
<button class="btn" @click="appendTodoItem">추가</button>
<ul>
<todo-item
v-for="item in items"
:key="item"
:name="item"
v-on:completed="completed"></todo-item>
</ul>
</div>`
});
8. 부모의 데이터가 변경 될 때 2 - 완료상태
Vue.component('todo-list', {
data() {
return {
inputItem: '',
items: [
{job: 'A', isComplete: false},
{job: 'B', isComplete: false},
{job: 'C', isComplete: false}
]
}
},
methods: {
completedItem(job, isComplete) {
const item = this.items.find(v => v.job === job);
item.isComplete = isComplete;
},
deleteItem(job) {
this.items = this.items.filter(v => job !== v.job);
},
appendTodoItem() {
if (!this.inputItem) {
window.alert('할일을 입력해주세요.');
return false;
}
this.items.push({job: this.inputItem, isComplete: false});
this.inputItem = '';
}
},
template: `
<div>
<input class="input-text" type="text" v-model="inputItem"/>
<button class="btn" @click="appendTodoItem">추가</button>
<ul>
<todo-item
v-for="item in items"
:key="item.job"
:job="item.job"
:isComplete="item.isComplete"
v-on:completedItem="completedItem"
v-on:deleteItem="deleteItem"></todo-item>
</ul>
</div>`
});
- data: items의 데이터 구조 변경
- 할일 완료 기능 변경
- 할일 삭제 기능 추가
Vue.component('todo-item', {
props: ['job', 'isComplete'],
data() {
return {
_isComplete: false
}
},
mounted() {
this._isComplete = this.isComplete;
},
computed: {
printJob() {
return this.isComplete ?
`<span class="completed">${this.job}</span>`:
`${this.job}`
}
},
methods: {
completeJob() {
this._isComplete = !this._isComplete;
this.$emit('completedItem', this.job, this._isComplete);
},
deleteJob() {
this.$emit('deleteItem', this.job);
}
},
template: `
<li>
<span v-html="printJob"></span>
<button v-if="isComplete" class="btn" @click="deleteJob">삭제</button>
<button v-else class="btn" @click="completeJob">완료</button>
</li>`
});
- 작업전 완료 상태에 따른 렌더링
- 할일 완료 기능 변경
- 할일 삭제 기능 추가
끝으로...
- 컴포넌트 기반 개발의 이해가 없다면 vue의 장점을 살리지 못할 수 있음
- html의 복붙이 아닌 레고처럼 조립하여 페이지를 개발
- 컴포넌트는 일단 크게 만들고 분리