Vue 3.3新增了 defineModel
,他是一个新的编译器宏,主要用于简化组件中 v-model
的双向绑定声明,尤其在 <script setup>
语法中。
一、defineModel
的核心作用
defineModel
旨在简化父子组件间的双向数据绑定,替代传统手动声明 props
和 emit
的繁琐流程。它自动处理以下内容:
- 声明 Prop :自动生成与
v-model
绑定的prop
。 - 触发事件 :修改值时自动触发
update:modelValue
事件。 - 类型推断:支持 TypeScript 类型推断,无需额外类型声明。
二、基本用法
1. 默认 v-model
绑定
在子组件中直接使用 defineModel()
声明默认的 v-model
绑定:
vue
<!-- 子组件 Child.vue -->
<script setup>
const modelValue = defineModel()
</script>
<template>
<input
:value="modelValue"
@input="e => modelValue = e.target.value"
/>
</template>
父组件使用 v-model
绑定数据:
vue
<!-- 父组件 Parent.vue -->
<template>
<Child v-model="message" />
</template>
2. 带参数的 v-model
(多绑定)
支持多个 v-model
绑定,例如 v-model:title
和 v-model:content
:
vue
<!-- 子组件 Child.vue -->
<script setup>
const title = defineModel('title')
const content = defineModel('content')
</script>
<template>
<input :value="title" @input="e => title = e.target.value" />
<textarea :value="content" @input="e => content = e.target.value" />
</template>
父组件传递多个绑定:
vue
<!-- 父组件 Parent.vue -->
<template>
<Child
v-model:title="pageTitle"
v-model:content="pageContent"
/>
</template>
三、高级配置
1. 设置默认值
通过传递选项对象为 defineModel
设置默认值:
javascript
const modelValue = defineModel({ default: '初始值' })
2. 类型验证
结合 TypeScript 进行类型校验:
typescript
const modelValue = defineModel<string>({ required: true })
3. 自定义修饰符
处理 v-model
修饰符(如 .trim
):
vue
<!-- 父组件 -->
<Child v-model.trim="text" />
<!-- 子组件 -->
<script setup>
const modelValue = defineModel({
set(value) {
// 应用修饰符逻辑(如 trim)
return value.trim()
}
})
</script>
四、与传统方式的对比
1. 传统方式(显式 props
+ emit
)
vue
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
function handleInput(e) {
emit('update:modelValue', e.target.value)
}
</script>
<template>
<input :value="modelValue" @input="handleInput" />
</template>
2. 使用 defineModel
简化
vue
<script setup>
const modelValue = defineModel()
</script>
<template>
<input :value="modelValue" @input="e => modelValue = e.target.value" />
</template>
优势:减少样板代码,提升可读性,自动处理事件触发。
五、注意事项
-
仅限
<script setup>
defineModel
是编译器宏,仅在<script setup>
中可用。 -
版本兼容性
需 Vue 3.3+ 支持,确保项目依赖版本正确。
-
避免与手动
props
冲突不要手动声明与
defineModel
同名的props
,否则会导致覆盖或冲突。 -
复杂逻辑需回退传统方式
如需自定义事件名或复杂校验逻辑,仍需使用
defineProps
+defineEmits
。 -
修饰符处理
若父组件使用修饰符(如
.lazy
),需在子组件中显式实现其逻辑。
六、总结
- 简化双向绑定 :
defineModel
大幅减少v-model
的声明代码。 - 多绑定支持 :轻松处理多个
v-model
参数(如v-model:title
)。 - 类型安全:天然支持 TypeScript 类型推断。
- 适用场景:推荐在简单双向绑定场景中使用,复杂场景可结合传统方式。
现在,使用 defineModel
,可以显著提升 Vue 3 组件的开发效率和代码可维护性。