v-model을 사용가능한 컴포넌트
<input>
<select>
<textarea>
v-model의 수식어
.lazy
-input
대신change
이벤트를 수신함..number
- 유효한 입력 문자열을 숫자로 변환하여 전달..trim
- 사용자 입력의 공백을 트리밍. (e.g : v-model.trim="inputValue")
1.단방향 바인딩
아래의 input으로 내용을 변경해도 msg는 변경되지않는다
그러나 msg 변수를 직접 변경함으로써 변경된다
const msg=ref('test')
<input type="text" :value="msg" />
<h1>{{ msg }}</h1>
2. 양방향 바인딩 (v-model 사용)
아래처럼 v-model을 사용하면 input에서 값을 변경하면 msg가 변경된다
msg변수가 변경된다
const msg=ref('test')
<input v-model="msg" />
<h1>{{ msg }}</h1>
↓
실제로는 내부적으로는 아래와 같이 컴파일되어 처리된다
<input
:value="msg"
@input="msg = $event.target.value"
/>
3.일반적인 Emit 사용 예제
** 부모 컴포넌트 **
const msg=ref('test')
function changeMsgFunc(newValue){
msg.value = newValue
}
<자식컴포넌트 :msg="msg" @change-msg="changeMsgFunc" />
** 자식 컴포넌트 **
const emit = defineEmits(["change-msg"]);
...
emit('change-msg','변경값')
4.Emit 양방향 바인딩 (v-model사용)
4-1 간단한 방법
v-model만 사용하는 방법
<!-- Parent.vue -->
<script setup>
import Child from './Child.vue'
import { ref } from 'vue'
const msg = ref('Hello World!')
</script>
<template>
<h1>{{ msg }}</h1>
<Child v-model="msg" />
</template>
<!-- Child.vue -->
<script setup>
const model = defineModel()
</script>
<template>
<span>My input</span>
<input v-model="model">
</template>
4-2 조금 긴 방법
update:modelValue을 사용하는 방법
<!-- Child.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
<!-- Parent.vue -->
<Child
:modelValue="foo"
@update:modelValue="$event => (foo = $event)"
/>
조금 긴 방법을 사용했을때 내부구조 ↑
아래처럼 v-model을 사용하면 부모컴포넌트에서 emit을 선언하지않아도 msg변수가 변경된다
** 부모 컴포넌트 **
const msg=ref('test')
<자식컴포넌트 v-model="msg"/>
↓
실제로는 내부적으로는 아래와 같이 컴파일되어 처리된다
** 부모 컴포넌트 **
const msg=ref('test')
<자식컴포넌트
:modelValue="mgs"
@update:modelValue="newValue => msg = newValue"
/>
** 자식 컴포넌트 **
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
// const emit = defineEmits(['update:modelValue'])
// emit('update:modelValue', 입력값..)
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
5.Emit 다른 사용법
굳이 v-model이 아니라도 위의 예제를 변형해 아래와 같이 사용가능
** 부모 컴포넌트 **
const msg=ref('test')
<자식컴포넌트
:checked="msg"
@update:checked="newValue => msg = newValue"
/>
** 자식 컴포넌트 **
defineProps(['checked'])
defineEmits(['update: checked'])
<template>
<input
:value="checked"
@input="$emit('update:checked', $event.target.value)"
/>
</template>
2024/01/16 기본적인 쌍방향 통신 예제
부모 컴포넌트 (ParentComponent.vue)
<template>
<section class="container">
<Child :message='testData' @update='update'></Child>
</section>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Comp.vue';
const testData = ref('beforeData');
function update(message) {
testData.value = message
}
</script>
자식 컴포넌트 (ChildComponent.vue)
<template>
<h2>{{ message }}</h2>
<button @click="change()">change</button>
</template>
<script setup>
import { ref } from 'vue';
import { defineProps, defineEmits } from "vue"
const props = defineProps(["message"]);
const emit = defineEmits(["update"])
const messageLocal=ref(props.message)
function change(){
messageLocal.value="afterData"
emit("update", messageLocal.value)
}
</script>
2024/01/20 추가 ( 위의 예제를 말로 풀면 아래와 느낌 )
1.부모 ref정의후 props로 넘긴다
↓
2.자식 props로 받은후 해당 props를 HTML에 기입한다 ( * 만약 여기서 props가 아니라 props를 ref에 넣은 변수등을 HTML에 넣으면 변화가 적용이 안된다 )
3.emit으로는 부모에게 보낼땐 props가 변경이 안되기때문에 새로운 변수등에 할당해서 보낸다
6.자식 컴포넌트에서 데이터 변경하는 경우 (24/2/4추가)
부모에서 자식으로 props로 전달한 데이터는
자식에서 받은 props를 그대로 설정하기만해도
부모에서 데이터 변경시 자식 데이터가 자동으로 변경이 된다
그러나 간혹 자식에서 부모의 데이터를 변경해야하는 경우가 있는데
이 경우는 props를 직접 변경할수 없기때문에 그에 따른 대처법이다
1.computed를 사용
아래의 1 ,2, 3 순서로 데이터를 전달하며 부모에 emit된 값을 다시 props로 받아온뒤 1이 실행된다
<input v-model="modifiedData"/> // 2
// 여기서 v-model을 사용하면 내부적으로 자체적인 @input함수( event => text = event.target.value )를 사용하게 되며 3번이 호출된다
const modifiedData = computed({
// 1
get: () => parentData.value,
// 3
set: (value) => {
emit('updateData', value);
},
});
2.watch사용
ref(props.parentData)를 사용하면 초기 값만 설정되고, 부모 컴포넌트의 parentData가 변경되어도 자식 컴포넌트의 modifiedData는 자동으로 업데이트되지 않는다.
그러므로 watch를 사용해서 부모로 부터 받는 props.parentData를 감시해야한다.
아래의 1 ,2, 3 순서로 데이터를 전달하며 부모에 emit된 값을 다시 props로 받아온뒤 1이 실행된다
<input :value="modifiedData" @input="notifyParent" />
const modifiedData = ref(props.parentData); // 1 (자식화면에서 사용할 반응성 변수 초기화)
watch(() => props.parentData, (newValue) => {
modifiedData.value = newValue; // 4 아래의 3에서 갱신한 부분이 1번에 갱신되지 않기때문에 watch로 부모로 부터 받은 값을 감시해서 갱신해준다
});
const notifyParent = (e) => {
modifiedData.value = e.target.value; // 2 (자식화면에서 사용할 반응성 변수 갱신)
emit('updateData', modifiedData.value); // 3 부모값 변경, 그러나 1번 부분이 갱신되지않음
};
참조