Study/Vue3

[Vue3] 자식컴포넌트 input value값 가져오기 (defineModel)

hyjang 2024. 12. 10. 16:48
728x90

input 태그를 컴포넌트화하여 form 섹션 안에 포함시키려고 한다.

각각의 input 컴포넌트 value값을 가져와서 부모 컴포넌트에서 사용하려면 어떻게 해야할까?

 

 

원래는 자식 컴포넌트에서 emit으로 value값을 부모한테 보내고 부모는 그 value값을 가져오는 과정을 거쳐야하지만,

defineModel을 이용하면 다른 함수 없이 바로 value값을 가져올 수 있다.

 

자식 컴포넌트

#inputText.vue
<template>  
    <input 
      v-model="modelValue"
      type="text" 
    /> 
</template>

<script lang="ts" setup>  
  const modelValue = defineModel();
</script>

 

부모 컴포넌트

<template 
    <InputText 
      v-model="title" 
    /> 
</template>

<script setup lang="ts">
  import { ref } from 'vue'; 
 
  const title = ref('');
  
</script>

 

이렇게하면 부모 컴포넌트에 있는 변수 title에 InputText 컴포넌트에서 input 태그에 입력한 value값이 저장된다. 

 

radio나 select input도 가져올 수 있다.

 

input[type="radio"] 

# inputRadio.vue
<template>  
  <label  
  >
    {{ labelText }}
    <input
      v-for="item in radioArray"
      :key="item.inputValue"
      type="radio" 
      :value="item.inputValue"
      :checked="item.checkedBoolean"
      v-model="modelValue"
    /> 
  </label>
</template>

<script lang="ts" setup>
  import { inputRadioData } from '@/common.type';

  defineProps<{ 
    labelText: string;
    radioArray: inputRadioData[];
  }>();
  const modelValue = defineModel();
</script>

radio 버튼은 여러개가 필요하기 때문에 v-for를 이용해서 배열로 전달해준다.

 

특이한점은 input이 여러개라 그런지 :value와 v-model을 둘다 써줘야 한다.

:value에는 현재 input값의 value값이 있고 v-model은 선택이 되었을때 그 값을 부모 컴포넌트로 전달하는 것으로 보인다. 

 

부모 컴포넌트

<template>
 	<InputRadio
      :labelText="'중요도'" 
      :radioArray="importantRadio"
      v-model="important"
    />
 </template>
 
 <script lang="ts" setup>
  import { ref } from 'vue';
  const important = ref<string>('important1');

  const importantRadio = ref<inputRadioData[]>([
    {
      inputValue: 'important1',
      checkedBoolean: true,
    },
    {
      inputValue: 'important2',
    },
    {
      inputValue: 'important3',
    },
  ]);
 </script>

 

inputValue로 각각 전달한 :value값을 선택하면 "important"에 저장되어 important.value로 값을 가져올 수 있다.

 

input[type="select"]

#inputSelect.vue
<template> 
  <select 
    v-model="modelValue"
    @change="handleChange"
  >
    <option
      :value="item.optionValue"
      :selected="item.selectedBoolean"
      v-for="item in optionDataArray"
      :key="item.toString"
    >
      {{ item.optionText }}
    </option>
  </select>
</template>

<script setup lang="ts">
  import { optionData } from '@/common.type';

  defineProps<{
    className: string;
    handleChange?: () => void;
    optionDataArray: optionData[];
  }>();
  
  const modelValue = defineModel();
</script>

 

select 태그는 @change 이벤트가 필요하고 v-model를 추가해주며, option 태그에 :value를 추가해준다.

 

부모 컴포넌트

<template> 
      <FbSelect
        :className="'filter__searchSelect'"
        :handleChange="sortTodo"
        :optionDataArray="sortOption"
        v-model:="filterSortTodo"
      /> 
</template>

<script setup lang="ts"> 
  import { ref } from 'vue';  
   
  const filterSortTodo = ref('latest'); 
  const sortOption = ref<optionData[]>([
    {
      optionValue: 'latest',
      optionText: '최신순',
      selectedBoolean: true,
    },
    {
      optionValue: 'oldest',
      optionText: '오래된순',
    },
    {
      optionValue: 'important',
      optionText: '중요도순',
    },
  ]); 

  /**
   * 정렬 함수
   */
  const sortTodo = () => {
    emit('sortTodo', filterSortTodo.value);
  };
</script>

 

select를 선택하면 v-model로 해당 option의 value값을 가져온다.

@change 함수를 연결하여 이벤트를 줄 수도 있다.