v-model implementation in Vue.js 3
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> |
