当前位置: 首页 > news >正文

Vue : defineModel()

一、核心概念重述:组件中使用 v-model 的新方式

        在 Vue 3.4 及以上版本中,推荐使用 defineModel()来实现组件的双向数据绑定。它简化了以往通过 props emit 手动实现 v-model 的繁琐过程。

✅ 示例回顾

<!-- Child.vue -->
<script setup>
const model = defineModel()
</script><template><input v-model="model" />
</template>

父组件:

<!-- Parent.vue -->
<Child v-model="countModel" />

子组件中的 model 是一个 ref,与父组件的 countModel 实现双向同步。

二、底层机制详解

    defineModel() 是一个编译时宏(compile-time macro),会被自动展开为传统的 prop + emit 模式。

🔧 编译前(Vue 3.4+ 推荐写法):

const model = defineModel()

⚙️ 编译后等效代码(Vue ❤️.4 写法):

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])// 模拟 ref 行为
const model = computed({get: () => props.modelValue,set: (value) => emit('update:modelValue', value)
})

🔄 父组件的 v-model 展开为:

<Child :modelValue="foo" @update:modelValue="val => foo = val" 
/>

三、语法进阶:参数、默认值与修饰符

1. 带参数的 v-model

可以指定不同的模型名称,用于多个绑定:

<UserName v-model:first-name="first" v-model:last-name="last" />

子组件接收:

const firstName = defineModel('firstName')
const lastName = defineModel('lastName')

相当于监听 :firstName@update:firstName

2. 设置默认值和校验

// 必填
const model = defineModel({ required: true })// 默认值
const model = defineModel({ default: 0 })

⚠️ 警告:若设置了 default 但父组件未传值,则父子状态会不一致!

示例:

const model = defineModel({ default: 1 }) // 子组件为 1
const myRef = ref() // 父组件为 undefined

👉 此时 myRef 不会自动更新为 1,造成不同步!

3. 自定义修饰符支持

defineModel() 支持解构获取修饰符信息:

const [model, modifiers] = defineModel()
console.log(modifiers) // 如 { capitalize: true }

结合 get / set 函数处理逻辑:

首字母大写 .capitalize 示例:
const [model, modifiers] = defineModel({set(value) {if (modifiers.capitalize) {return value.charAt(0).toUpperCase() + value.slice(1)}return value}
})
模板中使用:
<MyComponent v-model.capitalize="myText" />

4. 多个带修饰符的 v-model

<UserNamev-model:first-name.capitalize="first"v-model:last-name.uppercase="last"
/>

子组件分别获取修饰符:

const [firstName, firstNameModifiers] = defineModel('firstName')
const [lastName, lastNameModifiers] = defineModel('lastName')console.log(firstNameModifiers) // { capitalize: true }
console.log(lastNameModifiers) // { uppercase: true }

四、知识点总结

知识点一:defineModel() 宏的作用

是一个编译宏,返回 ref,实现父子组件间双向绑定,替代手动声明 props emit

知识点二:v-model 参数机制

允许在组件上绑定多个 v-model,每个对应不同字段名(如 v-model:titletitle),提升灵活性。

知识点三:修饰符处理(.trim.number, 自定义)

通过 defineModel 返回的 modifiers 对象识别修饰符,配合 set 函数控制输入转换行为。

五、图表辅助理解

图表 1:defineModel() 编译原理流程图

图表 2:单个 v-model vs 多个 v-model 对比

特性单个 v-model多个 v-model
语法v-model="x"v-model:field="x"
子组件接收defineModel()defineModel('field')
底层 prop 名modelValuefield
事件名update:modelValueupdate:field
使用场景基础输入封装表单拆分字段绑定

图表 3:修饰符工作流程

六、最佳实践建议

推荐做法

  • Vue 3.4+ 优先使用 defineModel() 提高开发效率。

  • 多个字段绑定使用带参数的 v-model

  • 自定义修饰符时利用 set() 函数做值预处理。

🚫 避免陷阱

  • 不要轻易给 defineModel()default,除非父组件明确传值或初始化。

  • 注意类型安全,必要时配合类型注解(TS 用户)。

七、结语总结

    defineModel() 是 Vue 3.4 引入的重要语法糖,极大简化了组件双向绑定的实现方式。其背后仍基于 prop + emit 的响应式通信机制,但通过宏的方式隐藏了样板代码,使开发者能更专注于业务逻辑。

掌握其:

  • 基本用法,

  • 参数传递,

  • 修饰符处理,

        是构建高复用、易维护表单组件的关键技能。结合图表理解和实际演练,可快速上手并应用于复杂项目中。

http://www.dtcms.com/a/388900.html

相关文章:

  • 一套基于Java+Vue+UniApp开发的同城配送系统
  • Vue 3 手机外观组件库
  • 部署分布式CephFS,存储的服务器的最低配置
  • 【Spring AI】Ollama大模型-智能对话实现+项目实战(Spring Boot + Vue)
  • Vue 3 实战:GIS 系统模块化设计与多功能融合方案
  • Docker多容器编排:Compose 实战教程——从入门到精通
  • Vue2 基础知识点一:数据绑定 (Data Binding)
  • layui tree组件回显bug问题,父级元素选中导致子集全部选中
  • centos7上使用Docker+ RagFlow + ollama + 数据集 搭建自己的AI问答机器人(2025-09)
  • # 从 Gymnasium 到 Minari:新一代机器人强化学习工具链全指南
  • 系统架构设计师备考第27天——基于构件的软件工程
  • Centos下安装docker
  • OpenAPI 规范:构建高效 RESTful API 指南
  • 基于 AForge.NET 的 C# 人脸识别
  • SQLite与ORM技术解析
  • vue动态时间轴:交互式播放与进度控制
  • Java I/O三剑客:BIO vs NIO vs AIO 终极对决
  • AI 在视频会议防诈骗方面的应用
  • nest.js集成服务端渲染(SSR)
  • AI如何“听懂人话”?从语音识别到语义理解的最后一公里
  • 鸿蒙:Preferences持久化实现方案
  • 常温超导新突破!NixCu-O7材料设计引领能源革命(续)
  • 常温超导新突破!NixCu-O7材料设计引领能源革命
  • C++,C#,Rust,Go,Java,Python,JavaScript的性能对比
  • 《从崩溃到精通:C++ 内存管理避坑指南,详解自定义类型 new/delete 调用构造 / 析构的关键逻辑》
  • 鸿蒙:父组件调用子组件的三种方案
  • AppTest邀请测试 -邀请用户
  • 从零开始的云计算生活——第六十五天,鹏程万里,虚拟化技术
  • Java 开发指南:将 PDF 转换为多种图片格式
  • 【C++革命】董翔箭头函数库(xiang_arrow):在main函数里定义函数的终极方案