一、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
修饰符减少更新频率