Vue 3 组件 v-model 多个绑定
FreeGuideOnline
最新
2026-07-06
<ChildComponent :modelValue="parentData" @update:modelValue="parentData = $event" />
因此,子组件的 props 需要接收 `modelValue`,并在变更时触发 `update:modelValue` 事件。这是单一绑定的基础。
### 引入命名 v-model:实现多个绑定
Vue 3 的 v-model 支持参数传递,语法为 `v-model:xxx`,其中 `xxx` 是你自定义的名称。例如:
```html
<UserProfileForm
v-model:username="user.name"
v-model:email="user.email"
/>
上面的写法等价于:
<UserProfileForm
:username="user.name"
@update:username="user.name = $event"
:email="user.email"
@update:email="user.email = $event"
/>
子组件如何接收多个 v-model
子组件需要为每个 v-model 声明对应的 prop 和 emit 事件。事件名采用 update:propName 的格式。
假设我们构建一个自定义输入组件 UserProfileForm,它同时管理用户名和邮箱。
子组件 (UserProfileForm.vue)
<template>
<div>
<label>
用户名:
<input
:value="username"
@input="$emit('update:username', $event.target.value)"
/>
</label>
<label>
邮箱:
<input
:value="email"
@input="$emit('update:email', $event.target.value)"
/>
</label>
</div>
</template>
<script setup>
defineProps({
username: String,
email: String
})
defineEmits(['update:username', 'update:email'])
</script>
父组件使用
<template>
<UserProfileForm
v-model:username="user.name"
v-model:email="user.email"
/>
</template>
<script setup>
import { reactive } from 'vue'
import UserProfileForm from './UserProfileForm.vue'
const user = reactive({
name: '张三',
email: 'zhangsan@example.com'
})
</script>
这样,user.name 和 user.email 便实现了双向绑定,子组件内的输入变化会实时同步回父组件状态。
处理 v-model 修饰符
Vue 3 同样支持自定义 v-model 修饰符。当使用多个 v-model 时,修饰符可以通过 prop modelModifiers 或 xxxModifiers 传递(其中 xxx 是你的命名)。
例如,我们希望 username 的输入自动将首字母大写。
父组件添加 .capitalize 修饰符(该修饰符为自定义):
<UserProfileForm
v-model:username.capitalize="user.name"
v-model:email="user.email"
/>
子组件需要声明对应的 modifiers prop,并根据修饰符调整行为:
<script setup>
const props = defineProps({
username: String,
email: String,
usernameModifiers: { default: () => ({}) }
})
const emit = defineEmits(['update:username', 'update:email'])
function updateUsername(event) {
let value = event.target.value
if (props.usernameModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
emit('update:username', value)
}
</script>
<template>
<div>
<label>
用户名:
<input :value="username" @input="updateUsername" />
</label>
<!-- 邮箱部分保持不变 -->
</div>
</template>
如果使用默认的 v-model(无命名),修饰符会通过 modelModifiers prop 传入。
使用可组合函数简化多个 v-model
当组件包含多个 v-model 时,可以为每个绑定创建一个可复用的逻辑。例如封装一个 useModel 辅助函数:
import { computed } from 'vue'
export function useModel(props, name, emit) {
const event = `update:${name}`
return computed({
get: () => props[name],
set: (value) => emit(event, value)
})
}
然后在子组件中使用:
<script setup>
import { useModel } from './useModel'
const props = defineProps(['username', 'email'])
const emit = defineEmits(['update:username', 'update:email'])
const username = useModel(props, 'username', emit)
const email = useModel(props, 'email', emit)
</script>
<template>
<input v-model="username" />
<input v-model="email" />
</template>