双向数据绑定

在 Vue2 中,双向数据绑定的实现核心是 Object.defineProperty 数据劫持 + 发布 - 订阅模式,结合 v-model 指令完成视图与数据的双向联动。以下是 Vue2 双向绑定的具体原理与实现细节:

一、Vue2 双向绑定的核心原理

Vue2 借助 3 个核心模块 实现双向绑定:

  1. 数据劫持(Observer):通过 Object.definePropertydata 中的属性进行劫持,监听属性的 get(读取)和 set(修改)操作;
  2. 依赖收集(Dep):在属性被读取时,收集依赖该属性的视图组件(订阅者);
  3. 发布 - 订阅(Watcher):当属性被修改时,通知所有订阅者更新视图;同时监听视图的输入事件,反向修改数据。

二、Vue2 中 v-model 的实现

v-model 是 Vue2 双向绑定的语法糖,本质是绑定 value 属性 + 监听 input 事件,自动完成 “数据→视图” 和 “视图→数据” 的双向同步:

示例(输入框双向绑定):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<!-- v-model 等价于 :value + @input -->
<input v-model="message" />
<p>当前输入:{{ message }}</p>
</template>

<script>
export default {
data() {
return {
message: "初始内容"
};
}
};
</script>

等价于手动绑定:

1
2
3
4
5
6
7
<template>
<input
:value="message"
@input="message = $event.target.value"
/>
<p>当前输入:{{ message }}</p>
</template>

三、Vue2 双向绑定的流程(以输入框为例)

  1. 初始化阶段
    • Vue 实例化时,Observer 会遍历 data 中的 message,通过 Object.defineProperty 为其添加 getset
    • 视图渲染时,读取 message 触发 getDep 收集该视图对应的 Watcher(订阅者)。
  2. 数据→视图
    • 当代码中修改 this.message = "新内容" 时,触发 set 方法;
    • Dep 通知所有订阅的 WatcherWatcher 触发视图重新渲染,输入框内容同步更新。
  3. 视图→数据
    • 用户在输入框输入内容时,触发 input 事件;
    • 事件回调中修改 this.message = $event.target.value,再次触发 set,完成数据同步。

四、Vue2 双向绑定的局限性

由于依赖 Object.defineProperty,存在以下限制:

  • 无法监听对象新增属性(需用 Vue.set);
  • 无法监听数组的下标修改 / 长度修改(需用数组变异方法,如 push/splice)。