티스토리 뷰
페이지를 개발할 때 여러 종류의 input
태그가 필요할 수 있다. 예를 들어 이름이나 주소같은 단순한 텍스트를 입력하는 <input type="text>
, 전화번호를 입력받으면서 3-4-4자리로 끊어서 자동으로 '-'를 붙여주는 <input type="tel">
, 숫자를 입력받는 <input type="number">
등이 있을 수 있다. 그리고 이러한 기능을 가진 input 태그들 안에 여러가지 클래스나 함수가 포함되어 있는 경우가 대부분이다. 프로젝트에서 이러한 input 태그들이 여러 군데에서 사용된다면 매번 코딩하는 것보다 차라리 컴포넌트로 분리하는게 나을 수도 있다. 즉 input태그를 커스텀 컴포넌트화 시킴으로써, 각 input태그별로 특정 기능을 특화시킬 수 있다. 그렇다면 input태그를 커스텀 컴포넌트화 시키려면 어떻게 해야하는지 살펴보자.
우선 vue에는 input태그에 v-model
이라는 양방향 데이터 바인딩이라는 강력한 기능을 제공한다. 하지만 컴포넌트화 시켜서 부모-자식간의 관계가 형성되면 부모 컴포넌트에서 자식 컴포넌트로 v-model
를 별도로 연결시켜주어야만 양방향 데이터 바인딩 기능을 유지할 수 있다.
방법은 어렵지 않다. 사실 부모 컴포넌트 입장에서는 컴포넌트화하기 이전 코드와 동일하게 v-model="data"
를 걸어주기만 하면 된다. 이렇게만 하면 자식 컴포넌트의 props
에서 자동으로 modelValue
라는 이름으로 받을 수 있게 된다.
별도로 처리가 필요한건 자식 컴포넌트이다. 자식 컴포넌트에서도 v-model="modelValue"
로 처리할 수 있으면 좋으련만, 아쉽게도 불가능하다. 왜냐하면 자식 컴포넌트에서 props
의 값은 직접 변형이 불가능하기 때문이다. v-model
은 input태그의 value
와 @input
이벤트를 동시에 처리해주는 디렉티브인데, @input="modelValue = $event.target.value"
는 props
의 값을 직접 변형하는 코드이기 때문이다.
이를 해결하기 위해서는 자식 컴포넌트 입장에서는 부모 컴포넌트에게 emit()
으로 '값이 $event.target.value
'로 변했다는 정보만 전달하고, 실질적인 값의 변형은 부모 컴포넌트에서 진행되야 한다.
// MainPage.vue (parent)
<template>
<div>
<InputNumber v-model="number" />
<p>number : {{ number }}</p>
</div>
<div>
<InputText v-model="text" />
<p>text:{{ text }}</p>
</div>
</template>
<script>
import InputNumber from "@/components/InputNumber.vue";
import InputText from "@/components/InputText.vue";
import { ref } from "vue";
export default {
components: { InputNumber, InputText },
setup() {
let number = ref(0);
let text = ref("");
return {
number,
text,
};
},
};
</script>
// InputNumber.vue (child)
<template>
<input
type="number"
placeholder="number"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: {
// 부모 컴포넌트에서 내려준 v-model 값
modelValue: Number,
},
};
</script>
// InputText.vue (child)
<template>
<input
type="text"
placeholder="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: {
// 부모 컴포넌트에서 내려준 v-model 값
modelValue: String,
},
};
</script>
'Dev' 카테고리의 다른 글
게시판 Pagination(페이지네이션) 구현 (0) | 2023.05.01 |
---|---|
vue-router를 통한 페이지간 데이터 전달 (0) | 2023.04.24 |
vue에서 router내 DOM을 querySelector로 찾지 못하는 문제 (0) | 2023.04.04 |
vue3 modal 모달 열고 닫기 (0) | 2023.03.09 |
vue3 modal transition(모달 트랜지션) (0) | 2023.03.09 |