\n\n\n\n\n\n\n\n```\n\n### 4-2 조금 긴 방법\n\nupdate:modelValue을 사용하는 방법\n\n```\n\n\n\n\n\n\n (foo = $event)\"\n/>\n```\n\n### 조금 긴 방법을 사용했을때 내부구조 ↑\n\n아래처럼 v-model을 사용하면 부모컴포넌트에서 emit을 선언하지않아도 msg변수가 변경된다\n\n```\n** 부모 컴포넌트 **\nconst msg=ref('test')\n\n<자식컴포넌트 v-model=\"\bmsg\"/>\n```\n\n ↓\n\n실제로는 내부적으로는 아래와 같이 컴파일되어 처리된다\n\n```\n** 부모 컴포넌트 **\nconst msg=ref('test')\n\n<자식컴포넌트\n :modelValue=\"mgs\"\n @update:modelValue=\"newValue => msg = newValue\"\n/>\n```\n\n```\n** \b자식 컴포넌트 **\n\ndefineProps(['modelValue'])\ndefineEmits(['update:modelValue'])\n// const emit = defineEmits(['update:modelValue'])\n// emit('update:modelValue', 입력값..)\n\n\n```\n\n### 5.Emit\u001d 다른 사용법\n\n굳이 v-model이 아니라도 위의 예제를 변형해 아래와 같이 사용가능\n\n```\n** \b부모 컴포넌트 **\nconst msg=ref('test')\n<자식컴포넌트\n :checked=\"msg\"\n @update:\bchecked=\"newValue => msg = newValue\"\n/>\n\n** \b자식 컴포넌트 **\ndefineProps(['checked'])\ndefineEmits(['update: checked'])\n\n```\n\n**2024/01/16 기본적인 쌍방향 통신 예제**\n\n부모 컴포넌트 (ParentComponent.vue)\n\n```\n\n \n\n```\n\n자식 컴포넌트 (ChildComponent.vue)\n\n```\n\n \n\n```\n\n**2024/01/20 추가 ( 위의 예제를 말로 풀면 아래와 느낌 )**\n\n1.부모 ref정의후 props로 넘긴다\n\n↓\n\n2.자식 props로 받은후 해당 props를 HTML에 기입한다 ( \\* 만약 여기서 props가 아니라 props를 ref에 넣은 변수등을 HTML에 넣으면 변화가 적용이 안된다 )\n\n3.emit으로는 부모에게 보낼땐 props가 변경이 안되기때문에 새로운 변수등에 할당해서 보낸다\n\n### 6.자식 컴포넌트에서 데이터 변경하는 경우 (24/2/4추가)\n\n부모에서 자식으로 props로 전달한 데이터는\n\n자식에서 받은 props를 그대로 설정하기만해도\n\n부모에서 데이터 변경시 자식 데이터가 자동으로 변경이 된다\n\n그러나 간혹 자식에서 부모의 데이터를 변경해야하는 경우가 있는데\n\n이 경우는 props를 직접 변경할수 없기때문에 그에 따른 대처법이다\n\n**1.computed를 사용**\n\n아래의 1 ,2, 3 순서로 데이터를 전달하며 부모에 emit된 값을 다시 props로 받아온뒤 1이 실행된다\n\n```\n // 2 \n// 여기서 v-model을 사용하면 내부적으로 자체적인 @input함수( event => text = event.target.value )를 사용하게 되며 3번이 호출된다\n\nconst modifiedData = computed({\n // 1 \n get: () => parentData.value,\n // 3\n set: (value) => {\n emit('updateData', value);\n },\n});\n```\n\n**2.watch사용**\n\nref(props.parentData)를 사용하면 초기 값만 설정되고, 부모 컴포넌트의 parentData가 변경되어도 자식 컴포넌트의 modifiedData는 자동으로 업데이트되지 않는다.\n\n그러므로 watch를 사용해서 부모로 부터 받는 props.parentData를 감시해야한다.\n\n아래의 1 ,2, 3 순서로 데이터를 전달하며 부모에 emit된 값을 다시 props로 받아온뒤 1이 실행된다\n\n```\n\n\nconst modifiedData = ref(props.parentData); // 1 (자식화면\b에서 사용할 반응성 변수 초기화)\n\nwatch(() => props.parentData, (newValue) => {\n modifiedData.value = newValue; // 4 아래의 3에서 갱신한 부분이 1번에 갱신되지 않기때문에 watch로 부모로 부터 받은 값을 감시해서 갱신해준다\n});\n\nconst notifyParent = (e) => {\n modifiedData.value = e.target.value; // 2 (자식화면에서 사용할 반응성 변수 갱신)\n emit('updateData', modifiedData.value); // 3 부모값 변경, 그러나 1번 부분이 갱신되지않음\n};\n```\n\n---\n\n참조\n\n[v-model참조](https://siot0.tistory.com/84)\n\n[v-model참조2](https://velog.io/@falling_star3/Vue.js-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90-v-model-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0)\n\n[v-model참조3](https://itchallenger.tistory.com/821)\n\n[emit사용법](https://velog.io/@hosb/Vue3-props%EC%99%80-emit-%ED%99%9C%EC%9A%A9)\n","publisher":{"@type":"Organization","name":"WallyLog"}}
vuejs

v-model과 emit에 대해서

emit

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번 부분이 갱신되지않음
};

참조

v-model참조

v-model참조2

v-model참조3

emit사용법