- 컴포넌트에서
v-model
디렉티브를 사용하기 위해선 2가지 작업을 수행해야 한다.
<CustomInput>
예시로 작성해보자면,
- 네이티브
<input>
엘리먼트의 value
속성을 modelValue
프로퍼티에 바인딩한다.
- 네이티브
input
이벤트가 트리거되면 새로운 값으로 update:modelValue
사용자 지정 이벤트를 내보낸다.
- 실제 작동하는 코드는 아래와 같다.
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
- 이제
v-model
이 부모 컴포넌트에서 완벽하게 동작한다.
<template>
<CustomInput v-model="message" />
<p>{{ message }}</p>
</template>
<script>
import CustomInput from './components/CustomInput.vue';
export default {
components: {
CustomInput
},
data() {
return {
message: ''
}
}
}
</script>
1. v-model Arguments
- 컴포넌트의
v-model
은 modelValue
를 프로퍼티로, update:modelValue
를 이벤트로 사용한다.
v-model
에 인자를 전달하여 이러한 이름을 수정할 수 있다.
<CustomInput v-model:message="message" />
<CustomInput>
에서 props
명과 이벤트명을 변경해줘야 한다.
<template>
<input
type="text"
:value="message"
@input="$emit('update:message', $event.target.value)"
/>
</template>
<script>
export default {
props: ['message'],
emits: ['update:message']
}
</script>
2. v-model 멀티 바인딩
- 단일 컴포넌트 인스턴스에서 여러 개의
v-model
바인딩을 생성할 수 있다.
- 각
v-model
은 컴포넌트에서 추가 옵션 없이도 다른 prop
에 동기화된다.
<template>
<UserName
v-model:firstName="firstName"
v-model:lastName="lastName"
/>
<h4>{{ firstName }} {{ lastName }}</h4>
</template>
<script>
import UserName from './components/UserName.vue';
export default {
...
data() {
return {
firstName: 'Dohee',
lastName: 'Kang'
}
}
}
</script>
<template>
<input
type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"
/>
<input
type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"
/>
</template>
<script>
export default {
props: ['firstName', 'lastName'],
emits: ['update:firstName', 'update:lastName']
}
</script>
3. v-model Modifier
- Form 입력 바인딩에서 modifier가 있듯이 컴포넌트
v-model
에도 사용자 정의 modifier가 있다.
- 아래 예제는 문자열의 첫 글자를 대문자로 표시하는
v-model.capitalize
modifier이다.
<UserName v-model.capitalize="firstName" />
v-model
에 추가되는 modifier는 modelModifiers
프로퍼티를 통해 컴포넌트에 제공한다.
- 아래 예제는 빈 객체로 설정된
modelModifiers
프로퍼티를 포함하는 컴포넌트이다.
this.modelModifiers
- 컴포넌트
modelModifiers
프로퍼티에 capitalize
가 포함되어 있고 그 값은 v-model.capitalize="firstName"
에 설정되어 있어 true
가 출력된다.
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
created() {
console.log(this.modelModifiers);
}
}
</script>
@input
을 통해 emitValue
메서드가 실행되고 첫 글자를 대문자로 변경한 capitalizeVal
을 this.$emit
을 통해 업데이트한다.
<template>
<input
type="text"
:value="modelValue"
@input="emitValue"
/>
</template>
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
methods: {
emitValue(event) {
let capitalizeVal = '';
const value = event.target.value;
if (this.modelModifiers.capitalize) {
capitalizeVal = value.charAt(0).toUpperCase() + value.slice(1);
}
this.$emit('update:modelValue', capitalizeVal);
}
}
}
</script>
4. v-model Arguments와 Modifier 동시 작성 방법
- value :
modelValue
-> firstName
- modifier :
modelModifiers
-> firstNameModifiers
- emits :
update:modelValue
-> update:firstName
<UserName v-model:firstName.capitalize="firstName" />
<template>
<input
type="text"
:value="firstName"
@input="emitValue"
/>
</template>
<script>
export default {
props: ['firstName', 'firstNameModifiers'],
emits: ['update:firstName'],
created() {
console.log(this.firstNameModifiers)
},
methods: {
emitValue(event) {
let capitalizeVal = '';
const value = event.target.value;
if (this.firstNameModifiers.capitalize) {
capitalizeVal = value.charAt(0).toUpperCase() + value.slice(1);
}
this.$emit('update:firstName', capitalizeVal);
}
}
}
</script>