Select box with v-model updates lazy when mounting the component
Vue version
3.2.45
Link to minimal reproduction
Steps to reproduce
- Open link to minimal reproduction
- reload page
What is expected?
The select box should show option C
directly from the beginning
What is actually happening?
v-model
is behaving weirdly when a value is already set while mounting the component.
In the following example the select box initially shows option A
then the Component re-renders and shows the correct option C
. However the selected ref is set to 3
from the beginning according to the output in the console when I'm logging the selected
ref.
<template>
<div>
<select v-model="selected">
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref('3');
</script>
When using the v-bind
directive and @change
, everything works fine.
<template>
<div>
<select @change="(e) => selectedValue = e.target.value">
<option value="4" :selected="isSelected('4')">A</option>
<option value="5" :selected="isSelected('5')">B</option>
<option value="6" :selected="isSelected('6')">C</option>
</select>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const selected = ref('6');
const isSelected = (value) => selectedValue.value === value
</script>
Moreover, this error occurs only when using a select box. Other types of input fields (checkbox, radio button, text input) work. Also when doing the same in plain Vue 3 it works.
System Info
System:
OS: Linux 5.0 undefined
CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 0 Bytes / 0 Bytes
Shell: 1.0 - /bin/jsh
Binaries:
Node: 16.14.2 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 7.17.0 - /usr/local/bin/npm
npmPackages:
vue: ^3.2.25 => 3.2.45
Any additional comments?
I also created this Nuxt issue related to this topic: https://github.com/nuxt/nuxt.js/issues/15631
The same happens with a checkbox. Value is set after control is added to the dom which triggers transition animations.
@edison1105 I was wrong and my problem is not relative to this issue.
For some reason scrollIntoView()
triggers transition. Could it somehow be related to vue? Seems that this is browser behavior but I'm not sure
@edikdeisling
this is because scrollIntoView()
triggers forces layout/reflow and layout/reflow
will restart a CSS animation.
see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/
@edison1105 thank you for the info, extremely interesting!
But does it mean that vue renders input without taking into account the initial value of v-model
?
https://sfc.vuejs.org/#eNqVUk1v2zAM/SuELnGB2Ma+Lq5jdIcddu6wky+OTTdarA9ItNMi8H77KCtZ0i4YtoMhi3x8fHrkUXy2NptGFIUofeukJfBIo61qDSCVNY7gCA77NbRG2ZGwgxl6ZxSsuGwVYOFrjfYEynQ4wCbgE3Ij3t1fctNj68wQskfGjZqZCkhwuINNBceAi0gzYDaYJ85kGp/py4AKNT3K7SD1UyR8DVxtsTcOgeUz/2oNNyuzdoftHrszA4NiwVdN5rvEQ3KTu+kJ3X9Ss4HfpEIzUpJcv+4mNcl2/6/Ec/yZYeazzOO8eFJ8IVR2aAiXuZWdnGBKo+qqzPla1bRkpOYZAr1Y3NRiod+a51owepkdB5eTI/lvqsrx0GUPJzVwkLQDco32kqRhIWf+Mr+SwVdPL0NUFAQtLtR0KSzYj8E4eOeBX4uNu4+7NIdi3r4gtTg3/XnhCD5yXcFr1kVDFjeWZmIt4tamqrHZD280b3bsfEr4WhRnnlrwDod7LXZE1hd5Pmq7Z+ONyh84lzteVJ5l2hn18CF7n338xK/1dB3P0Kt068zBo+OOtVhfkeccnNClDnWHDt1fm73Bvmr4JvdH05MPs5h/Ad3AT88=
It means that mounted
hook is called before input
gets its value from v-model
. Is it an issue? It means that vue inserts input
into DOM with invalid state. Also feels a little unexpected that input already exists in the DOM during mounted hook of the previous element. But this can be expected if all component template inserted into DOM at once
From my perspective v-model
should set value during beforeMount hook before the element is inserted into DOM