Vue 3 v-model 双向绑定进阶:多 v-model、自定义修饰符与组件封装
test12026-10-053 次阅读
v-model 的本质
在 Vue 3 里,v-model 只是语法糖:默认展开成 modelValue 属性和 update:modelValue 事件。理解这一点后,组件就能支持多个 v-model、自定义修饰符,把双向绑定的能力封装得比原生 input 更顺手。
多 v-model 同时绑定
通过给 v-model 加参数(v-model:title),一个组件可以同时暴露多个双向绑定字段,比单一的 modelValue 更适合表单类组件。
<script setup>
const props = defineProps({
name: String,
email: String,
});
const emit = defineEmits(['update:name', 'update:email']);
</script>
<template>
<input :value="name" @input="emit('update:name', $event.target.value)" />
<input :value="email" @input="emit('update:email', $event.target.value)" />
</template>
父组件这样用,name 和 email 各自独立双向绑定:
<UserForm v-model:name="form.name" v-model:email="form.email" />
自定义修饰符
v-model 的修饰符(如 .trim、.number)在组件里通过 modelModifiers(单绑定)或 xxxModifiers(命名绑定)拿到。下面实现一个 capitalize 修饰符,让用户一输入就首字母大写。
<script setup>
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => ({}) },
});
const emit = defineEmits(['update:modelValue']);
function onInput(e: Event) {
let val = (e.target as HTMLInputElement).value;
if (props.modelModifiers.capitalize) {
val = val.charAt(0).toUpperCase() + val.slice(1);
}
emit('update:modelValue', val);
}
</script>
<template>
<input :value="modelValue" @input="onInput" />
</template>
<NameInput v-model.capitalize="username" />
带修饰符的命名 v-model
当多个 v-model 同时存在时,修饰符按字段名挂在对应的 xxxModifiers 上。下面给 title 加一个 trim 修饰符:
const props = defineProps({
title: String,
titleModifiers: { default: () => ({}) },
});
const emit = defineEmits(['update:title']);
function onTitleInput(e: Event) {
let val = (e.target as HTMLInputElement).value;
if (props.titleModifiers.trim) val = val.trim();
emit('update:title', val);
}
三个注意点
- defineModel 宏(Vue 3.4+)可以让上面的样板大幅简化:const name = defineModel('name'),直接读写 name.value 即可,不需要手写 props/emit。
- 修饰符只在父组件声明、子组件消费,二者命名要一致,否则修饰符对象为空。
- 复杂对象不要用 v-model 直接绑整个表单,逐个字段拆 v-model 更利于类型推导和单测。
T
test1
文章作者
v-model 的本质 在 Vue 3 里,v-model 只是语法糖:默认展开成 modelValue 属性和 up...
- 分类
- 技术
- 发布时间
- 2026-10-05
- 字数
- 约 1953 字
- 阅读
- 3 次
