v-model 是响应式系统与事件监听协同工作的语法糖,本质为 :value 绑定加 @input(或其他事件)监听,通过 Watcher 实现数据与视图双向同步;Vue 3 以 Proxy 替代 defineProperty,提升响应式能力但语义不变。

v-model 不是独立机制,而是响应式系统与事件监听协同工作的结果。它本身没有“单独的底层”,而是把数据劫持、依赖收集、视图更新、用户输入捕获这四块能力串起来,形成自动同步闭环。
响应式系统:让数据“可追踪”
Vue 2 使用 Object.defineProperty 对 data 中每个属性进行劫持,重写 getter 和 setter:
- getter 被访问时(比如渲染 {{ msg }}),触发依赖收集,把当前组件的 Watcher 记录进该属性对应的 Dep(依赖池);
- setter 被赋值时(比如 this.msg = 'hi'),通知 Dep 中所有 Watcher 执行更新,触发视图重渲染。
对嵌套对象递归处理,数组则通过重写原型方法(push/pop/shift 等)实现响应式。整个过程构建起“谁用了这个数据 → 数据变了谁要更新”的映射关系。
v-model 是语法糖,本质是 value + 事件绑定
在编译阶段,v-model="msg" 会被解析为:
立即学习“前端免费学习笔记(深入)”;
-
:value="msg"—— 单向绑定 input 的 value 属性; -
@input="msg = $event.target.value"—— 监听输入事件,反向同步数据。
不同表单元素行为略有差异:
- text/textarea:默认监听
input事件; - checkbox(单个):绑定布尔值,监听
change; - checkbox(多个):绑定数组,选中项自动 push/remove;
- select:根据 value 或 multiple 属性,自动匹配或收集选项值。
Watcher 作为桥梁,连接数据与视图
每个使用响应式数据的组件实例都拥有一个或多个 Watcher。它在初始化时主动读取 data 属性(触发 getter),完成依赖注册;当数据变化触发 setter 时,Dep 通知对应 Watcher,Watcher 再调用 update 方法,触发虚拟 DOM diff 和真实 DOM 更新。
v-model 所在的 input 元素,其 value 渲染依赖于 msg 的值,而它的 input 事件又负责修改 msg —— Watcher 正是确保这两端始终对齐的关键执行单元。
Vue 3 的升级:Proxy 替代 defineProperty
Vue 3 改用 Proxy 实现响应式,解决了 Vue 2 的几个硬伤:
- 无需递归遍历,能直接拦截对象新增/删除属性;
- 天然支持 Map/Set/WeakMap 等原生集合类型;
- 数组索引赋值(如 arr[0] = x)、length 修改均可被监听;
- v-model 在 Vue 3 中仍保持相同语义,但底层由 reactive() + effect() 驱动,逻辑更统一。
不过,v-model 作为语法糖的定位没变:它始终是「数据驱动视图」+「事件驱动数据」的组合封装,只是响应式引擎变得更强大、更简洁。


















