前端Vue: vue 双向绑定的原理是什么?

7 阅读2分钟

Vue 双向绑定的原理经历了从 Vue 2 的 Object.defineProperty​ 到 Vue 3 的 Proxy​ 的演进,以下是详细解析:


Vue 2 双向绑定原理(基于 Object.defineProperty)

核心:发布-订阅模式 + 数据劫持

// 1. 数据劫持:遍历对象属性,转为 getter/setter
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
  // 获取劫持
    get() {
      console.log('读取属性:', key)
      return val
    },
    设置劫持
    set(newVal) {
      if (newVal === val) return
      console.log('更新属性:', key, '新值:', newVal)
      val = newVal
     
    }
  })
}

v-model 的实现

<!-- 模板 -->
<input v-model="message">

<!-- 编译为 -->
<input 
  :value="message" 
  @input="message = $event.target.value">

Vue 3 双向绑定原理(基于 Proxy)

核心优势

  1. 性能更好:Proxy 是语言级别支持,无递归遍历开销
  2. 功能更强:支持数组索引修改、对象新增属性等
  3. 内存更优:惰性代理,按需响应
// 1. 响应式核心
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      const res = Reflect.get(target, key, receiver)
      // 依赖收集
      track(target, key)
      return typeof res === 'object' ? reactive(res) : res
    },
    set(target, key, value, receiver) {
      const oldValue = target[key]
      const result = Reflect.set(target, key, value, receiver)
      if (oldValue !== value) {
        // 触发更新
        trigger(target, key)
      }
      return result
    }
  })
}

完整工作流程

1. 初始化阶段

模板编译 → 创建响应式数据 → 渲染组件 → 建立依赖关系

2. 数据更新阶段

用户输入 → 触发 setter → 通知 Watcher/Effect → 
虚拟DOM Diff → 更新真实DOM


Vue 2 vs Vue 3 实现对比

特性Vue 2 (Object.defineProperty)Vue 3 (Proxy)
数组监听需重写数组方法(push/pop等)原生支持
新增属性需用 Vue.set()自动响应
性能初始化递归遍历所有属性惰性代理
嵌套对象递归深度遍历按需代理
兼容性IE9+IE 不支持

总结

Vue 双向绑定的本质是 数据变化驱动视图更新,视图交互更新数据​ 的闭环。其演进体现了前端框架对性能、开发体验、功能的不断追求。选择实现方案时需考虑:

  • 项目规模:大型项目推荐 Vue 3 + Composition API
  • 兼容需求:需兼容 IE 则用 Vue 2
  • 性能要求:高频更新场景可用 Proxy 优势