Search code examples
vue.js

DefineModel is acting strange


Is the following supposed to happen?

parent component:

<template>
 <child v-model:counter="counter" />
</template>
<script setup lang="ts">
import {ref} from 'vue';
import child from './child.vue';
const counter = ref(0);
</script>

child component:

<template></template>
<script setup lang="ts">
import {onMounted} from 'vue';
const counter = defineModel<number>('counter');
onMounted(()=>{
counter.value++; // now the counter should be 1
console.log(counter.value) // prints 0
});
</script>

After updating the model counter from inside the onMounted hook, the value of the model is still 0. This is strange and why is it like this?

Vue Playground


Solution

  • Apparently this is the expected behavior.

    According to this issue posted in GitHub, under the hood, the DefineModel macro mutates the model via the parent component. Therefore , the nextTick is supposed to give the latest value.

    <script setup lang="ts">
    import {onMounted, nextTick} from 'vue';
    const counter = defineModel<number>('counter');
    onMounted(()=>{
        counter.value++; // now the counter should be 1
        console.log(counter.value) // prints 0
        nextTick(()=>{
            console.log(counter.value) // prints 1
        });
    });
    </script>