一、v-model 的实现机制解析
1. 表单元素中的实现机制
v-model 的实现本质是通过 双向数据绑定语法糖,将 v-bind:value 与 v-on:input 组合封装。
<input v-model="message">
等价于以下代码:
<input
:value="message"
@input="message = $event.target.value"
>
• 数据 → 视图:通过 v-bind:value 将数据绑定到表单的 value 属性(或 checked、selected 等属性)
• 视图 → 数据:监听 input 事件(或其他适配事件),通过事件对象 $event.target.value 更新数据
二、 自定义组件中的实现机制
在自定义组件中,v-model 通过 props + 事件 的组合实现父子组件双向通信,且支持 多数据绑定(Vue 3 特性)。
1、父组件实现
通过 v-model:test_data 指定自定义 prop 名称,将父组件 data 变量绑定到子组件的 test_data prop
<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 变量会自动更新
// 接收父组件传递的 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 绑定时:
-
自动映射:
父组件的
v-model:test_data="data"会被编译为:<ChildComponent :test_data="data" @update:test_data="data = $event" />子组件的
emit('update:test_data', newValue)会触发父组件的数据更新。
四、v-model可以绑定多个
v-model支持 多字段扩展:
允许一个组件同时绑定多个独立字段(如 v-model:firstName 和 v-model:lastName)
<CustomInput
v-model:first-name="firstName"
v-model:last-name="lastName"
/>
(PS): 同时绑定多个独立数据流,需在子组件分别定义对应的 props 和 emit 事件
五、 注意事项
-
避免直接修改 prop :子组件应通过事件触发更新,而非直接修改父组件传递的 prop
若传递的数据是对象或者数组类型,建议 深拷贝一份,改完再emit
用 lodash 拷贝比较方便
npm install lodash
import _ from 'lodash'
let index = 2
const newDateList = _.cloneDeep(props.dateList) //深拷贝一份
newDateList[index].isActive = true // 修改拷贝后的数据
emit('update:dateList', newDateList) // 将拷贝后的数据,告知父组件
// dateList: [{
// day: "今天",
// date: "00.00",
// isActive: true,
// enabled: true,
// time_timestamp_JSDate: 1713120000,
// time_timestamp_moment: 42341414,
// UTC_str: "Tue Apr 15 2025 19:00:00 GMT+0800 (中国标准时间)"
// }]
-
复杂数据结构处理
对象类型数据需使用v-model的深层绑定特性(Vue 3 新增) -
性能敏感场景
高频输入场景建议使用.lazy修饰符减少更新频率