v-model ,在 vue3和 vue2中的区别
Vue 3 的 v-model
设计更简洁、灵活,减少了配置成本,同时支持更复杂的双向绑定场景,是对 Vue 2 语法的重要改进。
1. 自定义组件的默认 Prop 和事件不同
Vue 2:
自定义组件使用v-model
时,默认绑定value
作为 prop,input
作为事件。
即<Child v-model="parentVal" />
等价于:<Child :value="parentVal" @input="parentVal = $event" />
<template><input :value="value" @input="$emit('input', $event.target.value)"/> </template><script> export default {name: 'CustomInput',props: {value: {type: String,default: ''}} } </script>
若要修改默认的 prop / 事件,需在子组件中通过
model
选项声明:// 子组件(Vue 2) export default {model: {prop: 'checked', // 自定义 prop 名event: 'change' // 自定义事件名},props: ['checked'] }
Vue 3:
自定义组件使用v-model
时,默认绑定modelValue
作为 prop,update:modelValue
作为事件。
即<Child v-model="parentVal" />
等价于:<Child :modelValue="parentVal" @update:modelValue="parentVal = $event" />
无需额外配置,直接在子组件中声明
modelValue
prop 即可:<!-- 子组件 --> <script setup>defineProps(['modelValue'])</script>
2. 支持多个 v-model
绑定
Vue 2:
一个组件只能有一个v-model
,若需多个双向绑定,必须手动绑定多个 prop 和事件:<Child :name="userName" @name-change="userName = $event":age="userAge" @age-change="userAge = $event" />
Vue 3:
支持通过参数化v-model
实现多个双向绑定,语法为v-model:propName
。
例如同时绑定name
和age
:<!-- 父组件 --> <Child v-model:name="userName" v-model:age="userAge" />
子组件中对应声明
name
和age
prop,并通过update:name
和update:age
事件更新:<!-- 子组件 --> <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
手动处理,逻辑繁琐:// 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
),处理更直接:<!-- 父组件使用修饰符 --> <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.valueif (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 直接实现 |