Vue에서 한글은 v-model이 아닌 input 이벤트로 받아야 하는 이유

yejineee·2021년 8월 18일
0

코드는 코드샌드박스에서 확인할 수 있다.

TL;DR

  • 한국어를 입력받을 때는 v-model이 아닌, input 이벤트에 state를 직접 변경하는 핸들러를 바인드시키도록 하자.

😱 오늘의 문제

오늘의 문제는 input에 한글을 입력하면 input 이벤트에 따라 state가 즉각 변경되지 않는 것에 있었다.

내가 원하는 바는 input에 값을 입력하면, 바로 바로 inputValue라는 반응형 값에 반영이 되도록 하는 것이었다.

하지만 아래처럼 한글을 입력하면, 인풋에 focus가 있으면 inputValue에 값이 반영이 안되었다...

그럼 validation을 하지 못할거고~ 슬퍼지고~ 이런저런 문제가 생긴다.

하지만, 영어는 state가 잘 변경되었다.

<template>
  <div>
    <h1>v-model</h1>
    <input v-model="state.inputValue" />
    <div id="input-length">length : {{ state.inputLength }}</div>
  </div>
</template>
<script>
import { computed, reactive } from "vue";
export default {
  setup() {
    const state = reactive({
      inputValue: "",
      inputLength: computed(() => state.inputValue.length),
    });
    return {
      state,
    };
  },
};
</script>

😀 해결쓰

이 문제의 해결책을 공식문서에서 찾았다. IMEInput Method Editor의 줄임말로, 한글이나 한자처럼 컴퓨터 자판에 있는 글자보다 수가 더 많은 문자를 조합해서 입력해주는 시스템 소프트웨어라고 한다.

For languages that require an IME (opens new window)(Chinese, Japanese, Korean etc.), you'll notice that v-model doesn't get updated during IME composition. If you want to respond to these updates as well, use an input event listener and value binding instead of using v-model.

내맘대로 번역하자면 ...

중국어, 일본어, 한국어처럼 IME가 필요한 언어는 v-model은 IME가 조합을 하는 동안 v-model은 업데이트되지 않는다. 조합을 해주는 동안에도 값이 변하는 것에 대응하고 싶다면, v-model을 사용하지 말고, input 이벤트 리스너에 value를 바인딩시켜라.

그렇군!

input 이벤트를 직접 감지하고, event.target.value를 state에 저장하는 식으로 수정하니, 바로바로 한글 입력이 state에 저장되었다.

<template>
  <div>
    <h1>Input Event</h1>
    <input @input="onInput" />
    <div id="input-value">value : {{ state.inputValue }}</div>
    <div id="input-length">length : {{ state.inputLength }}</div>
  </div>
</template>
<script>
import { computed, reactive } from "vue";
export default {
  setup() {
    const state = reactive({
      inputValue: "",
      inputLength: computed(() => state.inputValue.length),
    });

    const onInput = ({ target: { value } }) => {
      state.inputValue = value;
    };
    return {
      state,
      onInput,
    };
  },
};
</script>
<style scoped>
#input-length,
#input-value {
  font-weight: bold;
}
</style>

0개의 댓글