프레젠터 컴포넌트
그저 데이터를 보여주는
컨테이너=비즈니스 로직 컴포넌트
한 곳에서 데이터 조작이 일어나게끔
it's like Vuex의 축소판
하위 컴포넌트에서 각각 이뤄지던 할 일 데이터 추가, 삭제를 App이라는 컨테이너에서 한 번에 관리하고자 함
TodoInput의 newTodoItem
TodoList의 todoItems[]
로컬 스토리지의 todoItems
를 모두 하나로 통합
App.vue의 todoItems로 통합할 것
TodoList를 예로 들면,
원래는 새로고침을 해서 localStorage.getItem()
이 실행되어야 로컬 스토리지의 데이터가 TodoList내의 todoItems[]로 옮겨져올 수 있었던 것.
props를 통해 데이터를 받아온다는 건, 애초에 TodoList.vue 내에 App.vue의 todoItems(혹은 로컬 스토리지)
라는 부품이 끼워져 있는 것처럼 이해하면 될 듯 . 새로고침을 할 필요가 없이 바로 바뀐다.
App.vue
<template>
<div id="app">
<TodoList v-bind: propsdata="todoItems"></TodoList>
v-bind: 내려보낼 프롭스 속성 이름 = "현재 위치의 컴포넌트 데이터 속성"
</div>
</template>
<script>
export default {
data(){
return{
todoItems: []
이 todoItems를 propsdata라는 이름으로 TodoList에 내려보낸 것
}
}
}
</script>
TodoList.vue
<script>
export default {
props: ['propsdata']
}
</script>
상위 컴포넌트 - template 부분 - 하위 컴포넌트 태그 내에 v-bind로 내려보낼 데이터를 선언
하위 컴포넌트 - script 부분 - export dafault - props에서 상위 컴포넌트에서 설정한 데이터 이름으로 받기 ['상위 컴포넌트에서 설정한 프롭스 데이터 이름']
App.vue
<template>
<TodoInput @addTodoItem="addOneItem"></TodoInput>
<!--@하위 컴포넌트에서 발생시킨 이벤트 이름 = "현재 컴포넌트의 메소드 명"-->
<!--하위 컴포넌트의 이벤트 발생이 메소드 실행의 조건이 됨-->
</template>
<script>
methods: {
addOneItem(todoItem){
//하위 컴포넌트에서 올려보낸 인자를 todoItem이라는 이름으로 받음
var obj = {completed: false, item: todoItem};
localStorage.setItem(todoItem, JSON.stringify(obj));
this.todoItems.push(obj);
}
}
</script>
TodoInput.vue
<script>
export default {
methods: {
addTodo() {
if (this.newTodoItem !== ' '){
this.$emit('addTodoItem', this.newTodoItem)
// this.$emit('이벤트 이름', 인자1, 인자2, ...)
// 하위 컴포넌트에서 발생시킨 이벤트 == 하위 컴포넌트에서 상위 컴포넌트로 보내는 신호와도 같다
}
}
}
}
</script>
상위 컴포넌트 - template 부분 - 하위 컴포넌트 태그 내에 v-on으로 받아올 이벤트와 매핑할 상위 컴포넌트 내의 메소드 선언
하위 컴포넌트 - script 부분 - export default - 메소드 내에서 $emit을 통해 상위 컴포넌트에 전달할 이멘트 명과 인자를 선언
App.vue
<script>
export default {
methods: {
toggleOneItem(todoItem, index){
todoItem.completed = !todoItem.completed;
}
}
}
</script>
TodoList.vue
<template>
<div>
<ul>
<li v-for="(todoItem, index) in propsdata">
...
</li>
</ul>
</div>
</template>
toggleOneItem의 인자인 todoItem은 props를 통해 App.vue에서 받아온 데이터임
따라서 todoItem에서 데이터를 수정하기 보다는(불필요하게 하위 컴포넌트에 내려갔다 올라오는 것이므로) 컨테이너인 App.vue에서 바로 수정하는 것이 바람직하다.
App.vue
<script>
export default {
methods: {
toggleOneItem(todoItem, index){
this.todoItems[index].completed = !this.todoItems[index].completed;
}
}
}
</script>
데이터 관리는 컨테이너 컴포넌트에서만 이뤄지도록!