Vue 3 的 v-model
设计更简洁、灵活,减少了配置成本,同时支持更复杂的双向绑定场景,是对 Vue 2 语法的重要改进。
1. 自定义组件的默认 Prop 和事件不同
-
Vue 2 :
自定义组件使用
v-model
时,默认绑定value
作为 prop,input
作为事件。即
<Child v-model="parentVal" />
等价于:javascript<Child :value="parentVal" @input="parentVal = $event" />
子组件:
javascript<template> <input :value="value" @input="$emit('input', $event.target.value)" /> </template> <script> export default { name: 'CustomInput', props: { value: { type: String, default: '' } } } </script>
若要修改默认的 prop / 事件,需在子组件中通过
model
选项声明:javascript// 子组件(Vue 2) export default { model: { prop: 'checked', // 自定义 prop 名 event: 'change' // 自定义事件名 }, props: ['checked'] }
-
Vue 3 :
自定义组件使用
v-model
时,默认绑定modelValue
作为 prop,update:modelValue
作为事件。即
<Child v-model="parentVal" />
等价于:javascript<Child :modelValue="parentVal" @update:modelValue="parentVal = $event" />
无需额外配置,直接在子组件中声明
modelValue
prop 即可:javascript<!-- 子组件 --> <script setup> defineProps(['modelValue']) </script>
2. 支持多个 v-model
绑定
-
Vue 2 :
一个组件只能有一个
v-model
,若需多个双向绑定,必须手动绑定多个 prop 和事件:javascript<Child :name="userName" @name-change="userName = $event" :age="userAge" @age-change="userAge = $event" />
-
Vue 3 :
支持通过参数化
v-model
实现多个双向绑定,语法为v-model:propName
。例如同时绑定
name
和age
:javascript<!-- 父组件 --> <Child v-model:name="userName" v-model:age="userAge" />
子组件中对应声明
name
和age
prop,并通过update:name
和update:age
事件更新:javascript<!-- 子组件 --> <script setup> const props = defineProps(['name', 'age']) const emit = defineEmits(['update:name', 'update:age']) </script> <template> <input :value="name" @input="emit('update:name', $event.target.value)" /> <input :value="age" @input="emit('update:age', $event.target.value)" /> </template>
3. 修饰符处理方式不同
-
Vue 2 :
自定义组件使用
v-model
修饰符(如.trim
)时,需在子组件中通过model.modifiers
手动处理,逻辑繁琐:javascript// Vue 2 子组件处理修饰符 export default { model: { prop: 'value', event: 'input' }, props: { value: String, modifiers: { default: () => ({}) } // 接收修饰符 }, methods: { handleInput(val) { if (this.modifiers.trim) { val = val.trim() } this.$emit('input', val) } } }
-
Vue 3 :
修饰符会自动作为
modelModifiers
prop 传递(参数化v-model
则为propNameModifiers
),处理更直接:javascript<!-- 父组件使用修饰符 --> <Child v-model.uppercase="text" /> <!-- 子组件处理修饰符 --> <script setup> const props = defineProps({ modelValue: String, modelModifiers: { default: () => ({}) } // 自动接收修饰符 }) const emit = defineEmits(['update:modelValue']) const handleInput = (e) => { let val = e.target.value if (props.modelModifiers.uppercase) { // 直接使用修饰符 val = val.toUpperCase() } emit('update:modelValue', val) } </script>
总结:核心差异对比
特性 | Vue 2 中的 v-model |
Vue 3 中的 v-model |
---|---|---|
默认 prop / 事件 | value + input |
modelValue + update:modelValue |
多个双向绑定 | 不支持,需手动绑定多个 prop / 事件 | 支持 v-model:propName 语法 |
修饰符处理 | 需通过 model.modifiers 手动处理 |
自动解析为 modelModifiers prop |
自定义 prop / 事件名 | 需通过 model 选项配置 |
无需配置,通过 v-model:prop 直接实现 |