v-model implementation in Vue.js 3

#StandWithUkraine
Today, 20th March 2023, Ukraine is still bravely fighting for democratic values, human rights and peace in whole world. Russians ruthlessly kill all civilians in Ukraine including childs and destroy their cities. We are uniting against Putin’s invasion and violence, in support of the people in Ukraine. You can help by donating to Ukrainian's army.

In Vue3, alias for v-model, e.g.:

<Comp v-model="vv">

is prop modelValue + event @update:modelValue :

<Comp :modelValue="vv" @update:modelValue="vv = $event">

So, to create v-model in vue, you just need to read from reactive modelValue property in the component and emit event named "@update:modelValue". Check example below to understand how to do it.

Example

Create file MyInp.vue :

<template>
  <div class="inpwrap">
    <div class="lbl" :class="modelValue || inpFoc ? 'fill' : ''">
      {{ label }}
    </div>
    <input
      class="inp"
      :value="modelValue"
      @input="onInput"
      @focus='inpFoc = true'
      @blur='inpFoc = false'
    />
  </div>
</template>
<script>
export default {
  props: {
    modelValue: String,
    label: String,
  },
  data() {
    return {
      inpFoc: false,
    }
  },
  methods: {
    onInput(event) {
      this.$emit('update:modelValue', event.target.value)
    }
  },
}
</script>

<style scoped>
.inpwrap {
  width: 200px;
  margin-top: 30px;
  position: relative;
  margin-left: calc(50% - 100px);
}
.lbl {
  position: absolute;
  top: 10px;
  left: 10px;
  pointer-events: none;
  transition: 0.3s;
}
.lbl.fill {
  top: -8px;
  left: 5px;
  font-size: 14px;
  background-color: white;
  padding: 0 5px
}
.inp {
  width: 100%;
  box-sizing: border-box;
  padding: 10px;
  border: 1px solid #333;
  border-radius: 10px;
}
</style>

To connect file use:

<template>
  <div>
    <div>Hello, dear {{ name }} {{surname}}</div>
    <MyInp label="Name" v-model="name"></MyInp>
    <MyInp label="Surname" v-model="surname"></MyInp>
  </div>
</template>
<script>
import MyInp from './components/MyInp.vue'
export default {
  components: {
    MyInp
  },
  data() {
    return {
      name: '',
      surname: '',
    }
  },
}
</script>