v-model on a Component

In the quiz, Quantity got the count as a prop and asked for changes with two events. A component that edits one value of its parent is so common that Vue has a shortcut for it: v-model, which you know from text fields, works on your own components too. Here's a component for choosing the size of a cup:

<SizePicker v-model="size" />

In the component, defineModel() gives you that value as a ref:

<script setup>
const size = defineModel();
</script>

<template>
    <div class="sizes">
        <button :class="{ chosen: size === 'regular' }" @click="size = 'regular'">Regular</button>
        <button :class="{ chosen: size === 'large' }" @click="size = 'large'">Large</button>
    </div>
</template>

size looks like the component's own ref, but it isn't. Reading it gives the parent's size. Changing it emits an event, which v-model in the parent catches, and it changes the parent's size. So the data still lives in one place, the parent, and the component didn't have to declare a prop and an event. (Under the hood, that's what v-model on a component is: a prop named modelValue and an event named update:modelValue, which defineModel() declares for you.)

In the script, it's a ref like any other, size.value. And defineModel() takes the same options as a prop, for example defineModel({ type: String, required: true }).

Instructions

  1. Connect Quantity to the count of App.vue with v-model and defineModel(). The count shows between the buttons, the buttons change it, and the total changes with it.

  2. The count mustn't drop below 1: when it's 1, the − button is disabled (:disabled).