Vue3) 자식 컴포넌트에서 부모 컴포넌트로 데이터 전달(Props 방식)

호박이와 칼림바·2024년 4월 14일
0

Vue.js(2, 3)

목록 보기
3/4
post-thumbnail

📗목차


자식 컴포넌트에서 부모 컴포넌트로 데이터를 전달하는 방식을 TodoList 프로젝트로 예를 들어 설명해보겠다.
보통 자식 컴포넌트에서 emit을 사용해서 부모 컴포넌트로 올려 보내지만, props를 사용한 방식도 가능하다.

지금부터 그 방법에 대해 알아보자.

1. 컴포넌트 구조

먼저 컴포넌트의 구조를 보면,
TodoTemplate가 최상위 부모 컴포넌트이고, 제일 하위 컴포넌트는 TodoListItem이다.
TodoListItem에서 TodoTemplate까지 거슬러 올라가는 과정을 살펴보자.

2. Props 방식(함수로 전달)

props로 자식 컴포넌트에서 부모 컴포넌트로 전달하기 전에 먼저 부모 컴포넌트에서 자식 컴포넌트한테 props를 함수로 전달해줘야 한다.
TodoTemplateTodoListTodoListItem 순으로 props를 전달해줘야 한다.

아래 코드는 TodoTemplate에서 정의한 onUpdateonRemove 함수이다.

<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>

onUpdateonRemove 함수를 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>

onRemoveonUpdate 함수를 사용한 부분만 자세히 살펴보자.

<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함수에 해당 요소의 idtext 값을 최상위 TodoTemplate 컴포넌트에게 props로 다시 전달해주게 된다.

<button @click="onRemove(item.id)">
  <img src="../assets/images/free-icon-cancel.png" />
</button>

onRemove 함수는 버튼을 클릭 시 해당 요소의 id 값을 최상위 TodoTemplate 컴포넌트에게 props로 다시 전달해주게 된다.

3. 결과

TodoTemplate컴포넌트의 onUpdate 함수에 입력한 콘솔이 화면에 잘 출력되는 것을 볼 수 있다.

다음은 Emit을 사용해서,
자식 컴포넌트 => 부모 컴포넌트 데이터 전달 방식을 포스팅하겠다.

profile
프론트엔드 개발자입니다.

0개의 댓글

관련 채용 정보