当前位置:首页 > VUE

vue 双向绑定实现

2026-01-16 21:53:43VUE

Vue 双向绑定的实现原理

Vue 的双向绑定主要通过数据劫持结合发布者-订阅者模式实现,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。

数据劫持

Vue 2.x 使用 Object.defineProperty 劫持对象的属性,在属性被访问或修改时触发 getter 和 setter。Vue 3.x 改用 Proxy 代理整个对象,性能更好且能监听动态新增的属性。

vue 双向绑定实现

// Vue 2.x 数据劫持示例
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log('get:', val);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      console.log('set:', newVal);
      val = newVal;
    }
  });
}

依赖收集

每个响应式属性都有一个 Dep(依赖管理器),用于收集依赖该属性的 Watcher(订阅者)。在 getter 中收集依赖,在 setter 中通知更新。

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

模板编译

Vue 编译器将模板解析为渲染函数,过程中遇到指令(如 v-model)会生成对应的数据绑定代码。v-model 本质是 :value@input 的语法糖。

vue 双向绑定实现

// v-model 的等价形式
<input v-model="message">
// 等同于
<input :value="message" @input="message = $event.target.value">

实现简易双向绑定

以下是一个基于 Object.defineProperty 的极简实现:

function observe(obj) {
  Object.keys(obj).forEach(key => {
    let internalValue = obj[key];
    const dep = new Dep();
    Object.defineProperty(obj, key, {
      get() {
        dep.depend(); // 收集当前活跃的 Watcher
        return internalValue;
      },
      set(newVal) {
        internalValue = newVal;
        dep.notify(); // 通知所有 Watcher 更新
      }
    });
  });
}

class Dep {
  constructor() {
    this.subscribers = [];
  }
  depend() {
    if (activeUpdate) {
      this.subscribers.push(activeUpdate);
    }
  }
  notify() {
    this.subscribers.forEach(sub => sub());
  }
}

let activeUpdate = null;
function autorun(update) {
  function wrappedUpdate() {
    activeUpdate = wrappedUpdate;
    update();
    activeUpdate = null;
  }
  wrappedUpdate();
}

Vue 3 的改进

Vue 3 使用 Proxy 替代 Object.defineProperty,优势包括:

  • 直接监听整个对象而非属性
  • 可检测属性的新增和删除
  • 更好的性能表现
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key);
      return target[key];
    },
    set(target, key, value) {
      target[key] = value;
      trigger(target, key);
    }
  });
}

标签: 绑定双向
分享给朋友:

相关文章

react如何绑定事件

react如何绑定事件

React 事件绑定方法 在 React 中绑定事件有多种方式,以下是常见的几种方法: 使用 onClick 或其他事件属性直接绑定 <button onClick={() => co…

jquery绑定事件

jquery绑定事件

jQuery 绑定事件的方法 jQuery 提供了多种方式来绑定事件,以下是常见的几种方法: on() 方法 on() 是最推荐的事件绑定方法,支持动态元素和多个事件绑定。 $(selector)…

vue 实现循环绑定

vue 实现循环绑定

Vue 实现循环绑定的方法 在 Vue 中,可以通过 v-for 指令实现循环绑定,用于渲染列表或对象数据。以下是几种常见的实现方式: 数组循环绑定 使用 v-for 遍历数组,可以通过索引或直接获…

vue实现数组绑定

vue实现数组绑定

Vue 数组绑定的实现方法 Vue 提供了多种方式实现数组的响应式绑定,确保数据变化时视图自动更新。以下是常见的实现方法: 使用 v-for 指令渲染数组 通过 v-for 指令可以遍历数组并渲染…

实现vue动态绑定

实现vue动态绑定

动态绑定的基本语法 在Vue中,使用v-bind指令或简写:实现动态绑定,将数据属性与HTML元素的属性关联起来。例如动态绑定class或style: <div v-bind:class="{…

vue 双向绑定 实现原理

vue 双向绑定 实现原理

Vue 双向绑定的实现原理 Vue 的双向绑定是通过数据劫持结合发布者-订阅者模式实现的,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。以下是具…