v-model 双向绑定原理
面试速答(30 秒版 TL;DR)
- 本质:
v-model是语法糖,拆成 “传值 + 监听更新事件”。 - 原生表单:
v-model="x"约等于:value="x" @input="x = $event.target.value"(不同控件事件略有差异)。 - 组件上:
- Vue 2:默认
value+input(可用model选项改名)。 - Vue 3:默认
modelValue+update:modelValue(支持v-model:xxx多个模型)。
- Vue 2:默认
原生表单(最常见回答)
<template>
<input v-model="name" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const name = ref('');
</script>
等价理解(伪代码):
:value="name"@input="name = $event.target.value"
组件上的 v-model(Vue 3)
父组件:
<MyInput v-model="name" />
等价理解:
:modelValue="name"@update:modelValue="name = $event"
子组件(核心:接收 prop,发出 update 事件):
<template>
<input :value="modelValue" @input="onInput" />
</template>
<script setup lang="ts">
const props = defineProps<{ modelValue: string }>();
const emit = defineEmits<{ (e: 'update:modelValue', v: string): void }>();
function onInput(e: Event) {
emit('update:modelValue', (e.target as HTMLInputElement).value);
}
</script>
常见追问与坑
- 不要直接改 props:子组件不能
props.modelValue = ...,要通过emit('update:modelValue', ...)通知父组件改。 - 输入法合成(IME):中文输入过程中会触发 composition 事件,某些场景需要处理
compositionstart/compositionend避免抖动(多数情况下框架/浏览器已做得够好,但面试可提到意识点)。 - 修饰符:
v-model.trim/.number/.lazy会影响取值与触发时机(见“修饰符”那题)。