Vue3 input의 model과 화면에 보이는 값이 불일치하면?

1 minute read

환경

  • Vue 2.7
  • <script setup> 문법 사용

문제

v-model로 선택값을 전달받는 평범한 select 박스를 만들었음. 특정 option을 선택하면 validation 함수가 동작하여 안내문과 함께 해당 option을 선택하지 못하는 비즈니스 로직을 구현하려고 함.

그런데 문제가 발생했다. validation 함수 잘 동작했고, v-model의 변경을 차단했는데… 화면에는 방금 선택한 그 option 값이 선택되어 있었다. v-model이 변경되지 않았으니 option값은 변경 이전의 그 값으로 선택되어야 하지 않은가?

Vue 인스턴스 내부를 들여다보니, v-model의 값은 내 의도대로 잘 변경되어 있었다. 하지만 v-model이 바인딩 된 select box에는 엉뚱한 값이 찍혀 있었다.

원인

  • 1줄 요약: v-model이 변경되지 않았으니 rerender도 하지 않았기 때문이다.
  1. select 태그의 value는 html dom api에서 제공하는 값
  2. vue의 v-model로 input의 value(여기서는 selected)를 설정하면 그건 vue 인스턴스 내부의 값
  3. vue는 vue 인스턴스 내부의 값이 변경될 때 rerender를 함
  4. html dom api의 input value는 사용자가 입력했을 때 이미 변경되었음
  5. 하지만 vue 인스턴스 내부의 값이 변경되지 않았으니 rerender를 하지 않음
  6. vue의 v-model로 설정한 input value와 dom api의 input value가 따로 놀게 됨

해결책

여러 방법이 있지만, key를 변경하는 게 가장 깔끔한 방법이다.

<template>
  <MyComponent :key="componentKey" />
</template>
<script setup>
import { ref } from 'vue';
const componentKey = ref(0);

const forceRerender = () => {
  componentKey.value += 1;
};
</script>

괜히 이상한 짓, 이를테면 $forceUpdate 같은 걸 시도하느라 시간 낭비하지 말자.

참고

Tags:

Categories:

Updated:

Leave a comment