본문 바로가기
IT/개발

[Vue] DefineModel

by aloveu 2024. 4. 5.
반응형

 

부모로부터 받은 props를 바로 input에 v-model로 바인딩해서 수정도 되게 하고 싶다!!

모달을 부모에서 띄웠는데 자식 컴포넌트에서 바로 제어하고 싶다!!

 

네 이제 됩니다.

기존에는 부모로부터 props로 받은 값을 자식컴포넌트에서 다이렉트로 v-model에 바인딩하는 게 안 됐었습니다. 이건 단방향 데이터 흐름(One-way data flow) 원칙 때문입니다.

단방향 데이터 흐름은 데이터의 변경이 한 방향으로만 이루어지도록 하는 원칙입니다.
즉, 부모 컴포넌트에서 자식 컴포넌트로 데이터가 전달되고, 자식 컴포넌트에서는 이 데이터를 변경할 수 없습니다. 만약 자식 컴포넌트에서 props 데이터를 변경할 수 있다면, 데이터의 출처가 불분명해지고 예기치 못한 부작용이 발생할 수 있습니다.

 

그런데 이 원칙때문에 내가 원하는 걸 개발하려면 돌고 돌아 개발을 했었어야 했어요.

props로 받고 다른 ref 속성의 변수에 담아서 수정하고 그 이후에 값을 emit 해서 동기화하는 방법을 썼습니다. 

불편했어요.

또 다른 불편한 예로는 모달을 띄울 때 isShowModal 같은 props를 받아다가 닫기 처리를 해야할 때였어요.

emit으로 isShowModal을 부모로 올려서 false 처리해줘야했죠.

귀찮아요!

 

저만 느낀 게 아니었을까요?! 개발자들의 요구사항을 들어줬습니다.

더 유연한 개발 환경을 제공하기 위해서 Vue 3.3 버전부터는 defineModel이라는 매크로를 experimental 기능으로 쓸 수 있게 했다가 3.4 버전부터는 정식 피쳐로 쓸 수 있게 했습니다. 

 

 

이제 defineProps, defineEmits로 두 번씩 설정해야 하는 번거로움이 없어졌어요.

그럼 어떻게 쓰는지 코드로 정리해 보겠습니다.

| 부모 컴포넌트

<template>
  <div>
    <button @click="openModal">Open Modal</button>
    <MyModal v-model:isModalOpen="isModalOpen" v-model:modalData="modalData" />
  </div>
</template>

<script setup>
import MyModal from './MyModal.vue';

const isModalOpen = ref(false);
const modalData = ref({
  title: 'Modal Title',
  content: 'This is the modal content.',
});

function openModal() {
  isModalOpen.value = true;
}
</script>

 

| 자식 컴포넌트 (모달)

<template>
  <div class="modal">
    <div class="modal-header">
      <h2 name="title">{{ modelValue.title }}</h2>
      <button @click="closeModal">Close</button>
    </div>
    <div class="modal-body">
      <input v-model="modelValue.content">
    </div>
  </div>
</template>

<script setup>
const modelValue = defineModel('modelValue');
const isModalOpen = defineModel('isModalOpen');

function closeModal() {
  isModalOpen = false;
}
</script>

 

 

어때요? 참 쉽죠?

 

| 참고

https://vuejs.org/guide/components/v-model.html

반응형