frontend/Vue.js

[Vue3] v-model 사용하기(feat. emit, composition api)

김포레스트 2023. 6. 26. 16:41

참고링크 https://vuejs.org/guide/components/v-model.html

 

Component v-model | Vue.js

 

vuejs.org

 

 

v-model은 컴포넌트간 양방향 데이터 바인딩을 구현하는데 사용할 수 있다.

그리고, form 태그 안에서 사용할 수 있다.

<span> 이런데서 안통함

 

데이터를 보낼 컴포넌트

<template>
  <input v-model="searchText" @input="$emit('update:modelValue', $event.target.value)" />
</template>

<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

$emit 을 통해서 input 이벤트에 속해있는 props를 정의 함.

modelValue는 고정되어있는 props이기 때문에 바꾸면 안됨

 

데이터를 받을 컴포넌트

<template>
  <main>
    <testComponent v-model="searchText" />
    <p>{{ searchText }}</p>
  </main>
</template>

<script setup>
import { ref } from "vue";
import testComponent from './testComponent.vue';

const searchText = ref('');

</script>

호출한 컴포넌트 안에서 v-model을 사용하여 데이터를 지켜본다.

지켜본 데이터(바뀌는 데이터는 ref('')라는 반응형 데이터로 정의 해둔다.

 

결과물

 

 

modelValue 를 변형하기

보낼 컴포넌트

<template>
  <input type="text" :value="title" @input="$emit('update:title', $event.target.value)" />
</template>

<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>

아주 간략하다. :value 를 추가해서 props를 지정해주면 된다

바뀐 props는 title임. modelValue -> title로 바꾼 것임

 

받을 컴포넌트

<template>
  <main>
    <testComponent v-model:title="text" />
    <p>{{ text }}</p>
  </main>
</template>

<script setup>
import { ref } from "vue";
import testComponent from './testComponent.vue';

const text = ref('');

</script>

컴포넌트안에 v-model:title 추가 함.

 

 

v-model 여러개 사용하기(multiple)

보낼컴포넌트

<script setup>
defineProps({
  firstName: String,
  lastName: String
})

defineEmits(['update:firstName', 'update:lastName'])
</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>

modelValue 값을 쓰지 않고 임의로 props를 지정해서 쓸 때와 같은 방식임

대신 정의되는 props와 emits가 여러개인....

 

받을 컴포넌트

<template>
  <h1>{{ first }} {{ last }}</h1>
  <UserName
    v-model:first-name="first"
    v-model:last-name="last"
  />
</template>

<script setup>
import { ref } from 'vue'
import UserName from './UserName.vue'

const first = ref('김')
const last = ref('포레스트')
</script>

 

결과물 출력

 

 

v-model로 가져온 데이터 수정해서 사용하기

입력한 데이터 -> 바로 출력하기 도대체 무슨 의미가 있단 말인가!!!!!!!

역시 데이터는 지지고 볶고 물에말아서 써야 제맛 아닐까?

 

그래서 데이터를 수정하는 예제를 만들어 보도록 한다. 

달러를 입력하면 -> 원화로 변환하는 기능을 만들것이다. 

 

1. 보낼 컴포넌트에서 input으로 데이터를 받는다

2. 보낼 컴포넌트 안에서 데이터를 수정하는 function을 만든다

3. emit으로 보낸다

4. 받는 컴포넌트에서 출력

 

보낼 컴포넌트

<template>
  <input type="text" :value="title" @input="emitValue" />
</template>
<script setup>
const props = defineProps(['title'])
const emit = defineEmits(['update:title'])


function emitValue(e) {
  let value = e.target.value;
  
  value = 1306.11 * value;
  emit('update:title', value)
}
</script>

그냥 function에서 나온 value 값을 emit에 태워서 보내버리는 방식 같다. 

 

받는 컴포넌트

<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'
  
const myText = ref('')
</script>

<template>
  <MyComponent v-model:title.capitalize="myText" />
  <p>{{ myText }}</p>
</template>

그럼 얘는 보내준 밸류값을 계속 지켜봄👀👀👀

결과물 출력

 

 

지켜본다는 말이 조금 귀여운 것 같다.

 

사실은 안귀엽다

머리 터질것같음

 

저 코드의 문제점은 인풋에 입력을 하면서부터 결과값이 출력된다는 것이다.

빠릿해서 좋긴 한데, 인풋값은 그냥 그대로 두면 안될까?

 

어쨌든

오늘 정리 끝.