《v-model原理 》以及 《自定义组件实现v-model》

一、v-model 的实现机制解析

1. 表单元素中的实现机制

v-model 的实现本质是通过 双向数据绑定语法糖 ,将 v-bind:valuev-on:input 组合封装。

html 复制代码
<input v-model="message">

等价于以下代码

html 复制代码
<input 
  :value="message" 
  @input="message = $event.target.value"
>

数据 → 视图 :通过 v-bind:value 将数据绑定到表单的 value 属性(或 checkedselected 等属性)

视图 → 数据 :监听 input 事件(或其他适配事件),通过事件对象 $event.target.value 更新数据


二、 自定义组件中的实现机制

在自定义组件中,v-model 通过 props + 事件 的组合实现父子组件双向通信,且支持 多数据绑定(Vue 3 特性)。

1、父组件实现

通过 v-model:test_data 指定自定义 prop 名称,将父组件 data 变量绑定到子组件的 test_data prop

html 复制代码
<template> 
  <ChildComponent v-model:test_data="data" /> 
 </template> 
 
<script> 
  import ChildComponent from "./ChildComponent" 
  const data = ref('aaa') 
</script> 
   
<style> </style>

2、子组件实现

props 接收 :通过 test_data prop 接收父组件数据

事件触发 :通过 emit('update:test_data') 事件反向更新父组件数据

双向同步 :子组件修改数据后,父组件的 data 变量会自动更新

javascript 复制代码
// 接收父组件传递的 prop
const props = defineProps({
  test_data: {
    type: String,
    required: true
  }
});

// 定义事件发射器
const emit = defineEmits(['update:test_data']);

// 数据更新逻辑
const handleChange = (str) => {
  emit('update:test_data', str); // 触发自定义事件,告知父组件更新数据
}

三、 为什么定义emit事件为 update:xxx

update:xxx 是 Vue 的​​双向绑定约定语法​ ​,当父组件通过 v-model:test_data 绑定时:

  1. ​自动映射​​:

    父组件的 v-model:test_data="data" 会被编译为:

    html 复制代码
    <ChildComponent 
      :test_data="data" 
      @update:test_data="data = $event"
    />

    子组件的 emit('update:test_data', newValue) 会触发父组件的数据更新。

四、v-model可以绑定多个

v-model支持 ​​多字段扩展​​:

允许一个组件同时绑定多个独立字段(如 v-model:firstNamev-model:lastName

html 复制代码
<CustomInput 
  v-model:first-name="firstName" 
  v-model:last-name="lastName"
/>

(PS): 同时绑定多个独立数据流,需在子组件分别定义对应的 props 和 emit 事件

五、 注意事项

  1. 避免直接修改 prop
    子组件应通过事件触发更新,而非直接修改父组件传递的 prop
  2. 复杂数据结构处理
    对象类型数据需使用 v-model 的深层绑定特性(Vue 3 新增)
  3. 性能敏感场景
    高频输入场景建议使用 .lazy 修饰符减少更新频率
相关推荐
十一吖i7 分钟前
Vue3项目使用ElDrawer后select方法不生效
前端
只可远观8 分钟前
Flutter目录结构介绍、入口、Widget、Center组件、Text组件、MaterialApp组件、Scaffold组件
前端·flutter
周胡杰10 分钟前
组件导航 (HMRouter)+flutter项目搭建-混合开发+分栏效果
前端·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
敲代码的小吉米24 分钟前
前端上传el-upload、原生input本地文件pdf格式(纯前端预览本地文件不走后端接口)
前端·javascript·pdf·状态模式
是千千千熠啊25 分钟前
vue使用Fabric和pdfjs完成合同签章及批注
前端·vue.js
九月TTS1 小时前
TTS-Web-Vue系列:组件逻辑分离与模块化重构
前端·vue.js·重构
我是大头鸟2 小时前
SpringMVC 内容协商处理
前端
Humbunklung2 小时前
Visual Studio 2022 中添加“高级保存选项”及解决编码问题
前端·c++·webview·visual studio
墨水白云2 小时前
nestjs[一文学懂nestjs中对npm功能包的封装,ioredis封装示例]
前端·npm·node.js
满怀10152 小时前
【Vue 3全栈实战】从响应式原理到企业级架构设计
前端·javascript·vue.js·vue