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 次