Vue3 自定义组件实现 v-model 双向绑定
2026-04-02 13:49:04
0浏览
收藏
Vue 3 中的 v-model 双向绑定并非黑盒魔法,而是基于 `modelValue` prop 与 `update:modelValue` 事件的清晰契约;本文系统解析了自定义组件实现双向绑定的完整路径——从基础的手动声明 prop 和 emit 事件,到支持多模型绑定(如 `v-model:title`)、手动处理 `.lazy`/`.number`/`.trim` 等修饰符,再到 Vue 3.4+ 推荐的 `defineModel` 简化方案,帮你彻底掌握这一高频又易错的核心机制,写出更健壮、可维护、符合 Vue 最佳实践的自定义组件。

在 Vue 3 中,v-model 不再是语法糖的简单封装,而是基于 modelValue prop 和 update:modelValue 事件的显式约定。要让自定义组件支持双向绑定,关键在于正确暴露 prop、触发更新事件,并可选地支持自定义修饰符或多个 v-model。
基础写法:响应 modelValue 并触发 update 事件
组件需接收 modelValue prop,并在值变化时(如用户输入)通过 $emit('update:modelValue', newValue) 通知父组件:
- 在
defineProps 中声明 modelValue: { type: [String, Number, Boolean], default: '' }
- 用
defineEmits 声明 ['update:modelValue']
- 将原生元素的
v-model 指向 modelValue,并监听其变更(如 @input 或 @change)
例如,一个基础输入框组件:
<input<br> :value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
支持自定义 v-model 名称(如 v-model:title)
当需要多个双向绑定时(如表单中同时绑定 title 和 content),可通过 defineModel(Vue 3.4+)或手动声明实现:
- 使用
defineModel('title') 可直接获取响应式模型引用,自动处理 prop 和事件
- 旧版本可用
defineProps({ title: String }) + defineEmits(['update:title']),并在模板中用 :value="title" 和 @input="$emit('update:title', $event.target.value)"
- 父组件使用
处理修饰符(.lazy、.number、.trim)
Vue 3 不自动解析修饰符,需手动判断并响应:
- 在组件 props 中接收
modelModifiers: { default: () => ({}) }
- 检查
modelModifiers.lazy === true 时改用 @change 替代 @input
- 检查
modelModifiers.number 时,emit 前转为数字:parseFloat($event.target.value)
- 检查
modelModifiers.trim 时,emit 前调用 .trim()
结合 defineModel 简化开发(推荐 Vue 3.4+)
defineModel 是最简洁的方式,它返回一个响应式 ref,读写即触发更新:
const model = defineModel() → 默认绑定 modelValue
const title = defineModel('title') → 绑定 title,支持 v-model:title
- 模板中直接用
v-model="model" 或 v-model="title",无需手动 emit
- 修饰符也自动生效(如
v-model.number 会自动转数字)
不复杂但容易忽略细节,关键是理解 v-model 的本质是 prop + 事件契约,而不是魔法。
好了,本文到此结束,带大家了解了《Vue3 自定义组件实现 v-model 双向绑定》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!
- 下一篇
- Boss直聘如何向经理投简历?