v-model 是语法糖,vue 3 使用 modelvalue prop 和 update:modelvalue 事件,vue 2 使用 value prop 和 input 事件;支持多 v-model 绑定,需遵循约定并 emit 对应事件。

在 Vue 中,v-model 本质是语法糖,它默认绑定 value prop 并监听 input 事件(Vue 2)或 update:modelValue 事件(Vue 3)。要让自定义组件支持 v-model,关键不是“魔改”,而是**按约定提供 prop 和触发对应事件**。
Vue 3:使用 modelValue + update:modelValue(推荐)
这是 Vue 3 的标准方式,语义清晰、可扩展性强:
- 组件接收名为
modelValue的 prop(类型建议明确,如String、Number或Boolean) - 内部通过
$emit('update:modelValue', newValue)通知父组件更新 - 父组件写
<myinput v-model="searchText"></myinput>,等价于:<myinput :model-value="searchText"> searchText = val" /></myinput>
示例(一个带清空按钮的输入框):
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
@keydown.enter="$emit('confirm')">
<script setup></script>
const props = defineProps({
modelValue: { type: String, default: '' }
})
Vue 2:兼容 value + input(如需支持旧项目)
若仍在用 Vue 2,或需同时兼容 Vue 2/3(通过构建工具适配),则使用传统约定:
- prop 名为
value - 触发事件名为
input - 父组件写
<myinput v-model="text"></myinput>即可
注意:Vue 2 不支持多个 v-model,而 Vue 3 支持通过 v-model:xxx 绑定多个属性(如 v-model:checked、v-model:disabled),这对封装开关、复选框等组件非常实用。
进阶:支持多个 v-model(Vue 3)
比如封装一个搜索组件,既要绑定关键词,又要同步“是否展开”状态:
- 接收
modelValue(关键词)和expanded(展开状态)两个 prop - 分别触发
update:modelValue和update:expanded - 父组件可写:
<searchbar v-model="query" v-model:expanded="isExpanded"></searchbar>
此时组件内无需额外逻辑判断——每个 v-model:x 都是独立的双向绑定通道,干净解耦。
注意事项与最佳实践
-
不要在组件内部直接修改 prop:始终通过
$emit通知父组件变更,保持单向数据流 -
提供明确的 prop 类型和默认值:避免
undefined导致意外行为 -
清空、重置等操作必须 emit 事件:例如点击 × 按钮后,不能只设
internalValue = '',还要$emit('update:modelValue', '') -
文档里写清楚支持哪些 v-model 形式:方便使用者快速上手,比如注明“支持
v-model(关键词)和v-model:disabled”









