大宇宇宇
发布于 2025-08-31 / 6 阅读
0
0

数据双向绑定原理

在 Vue 中,数据双向绑定是通过 数据劫持 + 发布者-订阅者模式 实现的。


核心原理

  1. 数据劫持(响应式基础)

    • Vue 2.x:使用 Object.defineProperty() 劫持对象属性,为每个属性添加 gettersetter

      • getter:收集依赖(记录哪些组件依赖了该数据)。

      • setter:数据变化时触发依赖更新(通知相关组件重新渲染)。

    • Vue 3.x:改用 Proxy 代理整个对象,直接监听属性操作(包括数组索引变化、新增属性等),性能更优且无 Vue 2 的限制。

  2. 依赖收集与更新(发布者-订阅者模式)

    • 依赖收集:组件渲染时,访问数据触发 getter,将当前组件的 Watcher(订阅者)存入 Dep(依赖收集器)。

    • 触发更新:数据修改触发 setterDep 通知所有关联的 WatcherWatcher 调用组件更新函数(如 patch)重新渲染视图。

  3. 双向绑定(v-model)

    • 本质是 数据绑定(单向) + 事件监听 的语法糖:

      <input v-model="message" />

      <!-- 等价于 -->

      <input :value="message" @input="message = $event.target.value" />

    • 视图变化(如用户输入)通过事件更新数据,数据变化自动同步到视图。


关键角色

  • Observer:递归遍历数据,用 Object.definePropertyProxy 劫持属性,使其响应式。

  • Dep:依赖收集器,每个响应式属性都有一个 Dep 实例,管理该属性的 Watcher 列表。

  • Watcher:订阅者(如组件渲染函数、计算属性),数据变化时收到通知并执行更新。

  • Compile:解析模板指令(如 v-model),初始化视图绑定和事件监听。


流程简述

  1. 初始化

    • Observer 劫持数据,将其转为响应式。

    • Compile 编译模板,将 v-model 转为 :value + @input,并创建 Watcher

  2. 数据 → 视图

    • 数据变化 → setter 触发 → Dep 通知 WatcherWatcher 更新视图。

  3. 视图 → 数据

    • 用户输入 → 触发 @input 事件 → 更新数据 → 自动触发视图更新。


Vue 2 vs Vue 3

特性

Vue 2.x

Vue 3.x

数据劫持

Object.defineProperty

Proxy

监听范围

仅对象已知属性(无法监听数组索引/新增属性)

支持所有对象操作(含数组、动态属性)

性能

递归劫持属性,初始化较慢

惰性监听,性能更优


面试回答示例

“Vue 的双向绑定基于数据劫持和发布者-订阅者模式。
数据劫持:Vue 2 用 Object.defineProperty 为属性添加 getter/setter,Vue 3 用 Proxy 代理整个对象。
依赖管理getter 收集依赖(Watcher),setter 通知更新。
双向绑定v-model 是语法糖,通过数据绑定(value)和事件监听(@input)实现视图与数据的双向同步。
关键流程:数据变化触发 setter → 通知 Watcher → 更新视图;用户输入触发事件 → 更新数据 → 自动同步视图。”


常见追问点

  1. 为什么 Vue 2 无法监听数组索引变化?

    • Object.defineProperty 无法直接监听数组索引,需重写数组方法(如 pushsplice)。

  2. Proxy 的优势?

    • 直接监听对象,无需递归,支持动态属性和数组操作,性能更好。

  3. DepWatcher 的关系?

    • 一个响应式属性对应一个 DepDep 管理多个 Watcher(如多个组件依赖同一数据)。

掌握以上要点,可清晰阐述 Vue 双向绑定的核心机制。


评论