Interview question: please explain the principle of v-model
v-model can act on both form elements and custom components. In either case (vue2, vue3), it is a syntax sugar and will eventually generate an attribute and an event.
When it acts on a form element, vue will generate appropriate attributes and events according to the type of form element. For example:
- text and textarea elements use value property and input events;
- checkbox and radio use checked property and change events;
- The select field takes value as a prop and change as an event.
For custom components
vue2
v-model can also act on custom components. When it acts on custom components, it will generate a value attribute and input event by default.
Subcomponent HelloWorld
This sub component only implements the function of a simple counter, and then the event name I distribute upward is update:value. But vue2 if you use v-model, you will automatically change the event name to input.
<template> <div class="hello"> <button @click="change(value - 1)">-</button> <span>{{value}}</span> <button @click="change(value + 1)">+</button> </div> </template> <script> export default { name: "HelloWorld", props: { value: Number, }, methods: { change(val) { this.$emit("update:value", val); }, }, }; </script> Copy code
APP to use
<HelloWorld :value="inputVal" @update:value="inputVal = $event" /> Equivalent to <HelloWorld v-model="inputVal" /> Copy code
result:
Analyzing virtual dom results
vue2's virtual dom is viewed by using this in mounted_ Vnode, and then view componentOptions to view the properties passed by the component.
Developers can modify the sub component HelloWorld by changing the generated properties and events through the model configuration of the component
<template> <div class="hello"> <button @click="change(number - 1)">-</button> <span>{{ number }}</span> <button @click="change(number + 1)">+</button> </div> </template> <script> export default { name: "HelloWorld", props: { number: Number, }, model: { prop: "number", // The default is value event: "change", // The default is input }, methods: { change(val) { this.$emit("change", val); }, }, }; </script> Copy code
Parent component modification
<HelloWorld v-model="inputVal" /> <!-- Equivalent to --> <HelloWorld :number="inputVal" @change="data=$event" /> Copy code
effect
vue3
v-model can also act on custom components. When it acts on custom components, it will generate a modelValue property and onUpdate:modelValue event by default.
Subcomponent Comp
<script setup> import { ref, } from 'vue' const props = defineProps({ modelValue: Number }) const emits = defineEmits(['update:modelValue']); const change = (val) => { emits('update:modelValue', val) } </script> <template> <button @click="change(props.modelValue - 1)"> - </button> <span>{{props.modelValue}}</span> <button @click="change(props.modelValue + 1)"> + </button> </template> Copy code
Parent component App
<script setup> import { ref, getCurrentInstance } from 'vue' import Comp from './Comp.vue' const msg = ref(123); const internalInstance = getCurrentInstance(); console.log(internalInstance) </script> <template> <Comp v-model="msg"></Comp> Equivalent to <Comp :modelValue="msg" @update:modelValue="msg = $event"></Comp> </template> Copy code
result
Virtual dom analysis
vue3 uses ` ` getCurrentInstance 'to view the virtual dom, and uses props in children to view the property transfer
difference
Both vue2 and vue3 have v-model. The principle is to generate an attribute and an event, but there are some differences.
. sync modifier
The. sync modifier in vue3 is removed, and its function can be replaced by the parameters of v-model
For example:
<!-- vue2 --> <Comp :title="inputVal" @update:title="inputVal = $event" /> <!-- Abbreviated as --> <Comp :title.sync="inputVal" /> <!-- vue3 --> <Comp :title="inputVal" @update:title="inputVal = $event" /> <!-- Abbreviated as --> <Comp v-model:title="inputVal" /> Copy code
Multiple v-model s
vue3 allows you to write multiple v-models, which also strongly shows that v-model is a syntax sugar, which just helps you reduce the amount of code, that's all. vue2 cannot write multiple v-models
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> <!-- Is short for: --> <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" :content="pageContent" @update:content="pageContent = $event" /> Copy code
##v-model modifier
vue2.x is a self-contained modifier, but in the 3.x version, you can customize the modifier. The modifier in 3.x will be passed to the sub component as an attribute, and a modelModifiers attribute will be generated in the attribute. If this modifier exists, there will be a corresponding modifier and it is true. If it is not passed, it is undefined.
Modifying Comp subcomponents
<script setup> import { ref, } from 'vue' const props = defineProps({ modelValue: Number, modelModifiers: { default: () => ({}) } }) const emits = defineEmits(['update:modelValue']); const change = (val) => { // If the modifier range2 exists, add 1 and the subtraction will have no effect if(props.modelModifiers.range2){ val ++; } emits('update:modelValue', val) } </script> <template> <button @click="change(props.modelValue - 1)"> - </button> <span>{{props.modelValue}}</span> <button @click="change(props.modelValue + 1)"> + </button> </template> Copy code
Parent component usage
<Comp v-model.range2="msg"></Comp> Copy code
effect
vue3 test code address: vue2 test code address was deleted due to forgetting to log in 🤣🤣🤣