📗목차
자식 컴포넌트에서 부모 컴포넌트로 데이터를 전달하는 방식을 TodoList 프로젝트로 예를 들어 설명해보겠다.
보통 자식 컴포넌트에서 emit
을 사용해서 부모 컴포넌트로 올려 보내지만, props
를 사용한 방식도 가능하다.
지금부터 그 방법에 대해 알아보자.
먼저 컴포넌트의 구조를 보면,
TodoTemplate
가 최상위 부모 컴포넌트이고, 제일 하위 컴포넌트는 TodoListItem
이다.
TodoListItem
에서 TodoTemplate
까지 거슬러 올라가는 과정을 살펴보자.
props
로 자식 컴포넌트에서 부모 컴포넌트로 전달하기 전에 먼저 부모 컴포넌트에서 자식 컴포넌트한테 props
를 함수로 전달해줘야 한다.
TodoTemplate
→ TodoList
→ TodoListItem
순으로 props를 전달해줘야 한다.
아래 코드는 TodoTemplate
에서 정의한 onUpdate
와 onRemove
함수이다.
<script>
import TodoInsert from './TodoInsert.vue'
import TodoList from '../components/TodoList.vue'
import { ref } from 'vue'
export default {
name: 'TodoTemplate',
components: {
TodoInsert,
TodoList,
},
setup() {
const data = [
{ id: 0, content: '타입스크립트 공부하기' },
{ id: 1, content: '팀플하기' },
{ id: 2, content: 'Vue 공부하기' },
{ id: 3, content: '블로그 글 작성하기' },
]
const todos = ref(data)
const onCreate = text => {
const todo = {
id: todos.value.length + 1,
content: text,
}
todos.value.push(todo)
}
const onUpdate = (id, text) => {
console.log('TodoTemplate:', id, text)
todos.value[id].content = text
console.log('Edited todo:', todos.value.__v_raw)
}
const onRemove = id => {
todos.value = todos.value.filter(todo => todo.id !== id)
}
return {
todos,
onCreate,
onUpdate,
onRemove,
}
},
}
</script>
onUpdate
와 onRemove
함수를 TodoList
(자식 컴포넌트)에게 props
로 전달해주겠다.
TodoTemplate(최상위: 부모 컴포넌트)
<template> <div class="title">To do List</div> <TodoInsert :onCreate="onCreate" /> <div class="box"> <TodoList :todos="todos" :onRemove="onRemove" :onUpdate="onUpdate" /> </div> </template>
TodoList(자식 컴포넌트)
<template> <div class="todoList"> <TodoListItem v-for="item in todos" :key="item.id" :item="item" :onUpdate="onUpdate" :onRemove="onRemove" /> </div> </template>
그런 다음엔 TodoList
의 자식 컴포넌트에게(TodoListItem
) 또 한번 props
를 전달해줘야 한다.
그러고 나서 제일 하위 컴포넌트인 TodoListItem
에서 TodoTemplate
까지 props
로 데이터를 올려 보내보겠다.
아래의 코드를 봐보자.
TodoListItem(TodoList의 자식 컴포넌트)
<template> <div class="list"> <input type="checkbox" :id="item.id" v-model="isCheck" :class="{ hide: !isHide }" /> <label :for="item.id" :class="{ checked: isCheck, hide: !isHide }">{{ item.content }}</label> <div class="editBox" :class="{ hide: isHide }"> <input v-model="inputValue" /> <button type="button" class="saveBtn" @click="onUpdateHandler(item.id, inputValue)">save</button> </div> <div class="btnBox" :class="{ hide: isEdit }"> <button @click="toggleEdit"> <img src="../assets/images/free-icon-edit.png" /> </button> <button @click="onRemove(item.id)"> <img src="../assets/images/free-icon-cancel.png" /> </button> </div> </div> </template> <script> // 생략 setup(props) { // 생략 const inputValue = props.item.content const toggleEdit = () => { isHide.value = !isHide.value isEdit.value = !isEdit.value } const onUpdateHandler = (id, text) => { toggleEdit() props.onUpdate(id, text) } return { isCheck, isHide, isEdit, toggleEdit, inputValue, onUpdateHandler, } }, } </script>
onRemove
와 onUpdate
함수를 사용한 부분만 자세히 살펴보자.
<div class="editBox" :class="{ hide: isHide }">
<input v-model="inputValue" />
<button type="button" class="saveBtn" @click="onUpdateHandler(item.id, inputValue)">save</button>
</div>
<script>
setup(props) {
// 생략
const onUpdateHandler = (id, text) => {
toggleEdit()
props.onUpdate(id, text)
}
// 생략
}
</script>
save
버튼을 클릭 시 onUpdateHandler
함수를 실행한다.
그러면 props
로 전달받은 onUpdate
함수에 해당 요소의 id
와 text
값을 최상위 TodoTemplate
컴포넌트에게 props
로 다시 전달해주게 된다.
<button @click="onRemove(item.id)">
<img src="../assets/images/free-icon-cancel.png" />
</button>
onRemove
함수는 버튼을 클릭 시 해당 요소의 id
값을 최상위 TodoTemplate
컴포넌트에게 props
로 다시 전달해주게 된다.
TodoTemplate
컴포넌트의 onUpdate
함수에 입력한 콘솔이 화면에 잘 출력되는 것을 볼 수 있다.
다음은 Emit을 사용해서,
자식 컴포넌트 => 부모 컴포넌트 데이터 전달 방식을 포스팅하겠다.