当前位置:首页 > VUE

vue 双向绑定实现

2026-03-29 14:20:03VUE

Vue 双向绑定的实现原理

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

基于 Object.defineProperty 的实现(Vue 2.x)

  1. 数据劫持
    通过 Object.defineProperty 劫持对象的属性,在属性被访问或修改时触发 gettersetter

    function defineReactive(obj, key, val) {
      Object.defineProperty(obj, key, {
        get() {
          console.log(`读取 ${key}: ${val}`);
          return val;
        },
        set(newVal) {
          if (newVal !== val) {
            console.log(`设置 ${key}: ${newVal}`);
            val = newVal;
          }
        }
      });
    }
  2. 依赖收集
    getter 中收集依赖(Watcher),在 setter 中通知依赖更新。

    class Dep {
      constructor() {
        this.subscribers = new Set();
      }
      depend() {
        if (currentWatcher) {
          this.subscribers.add(currentWatcher);
        }
      }
      notify() {
        this.subscribers.forEach(watcher => watcher.update());
      }
    }
    
    let currentWatcher = null;
    function defineReactive(obj, key, val) {
      const dep = new Dep();
      Object.defineProperty(obj, key, {
        get() {
          dep.depend(); // 收集依赖
          return val;
        },
        set(newVal) {
          if (newVal !== val) {
            val = newVal;
            dep.notify(); // 通知更新
          }
        }
      });
    }
  3. Watcher 实现
    Watcher 负责订阅数据变化并执行回调(如更新视图)。

    vue 双向绑定实现

    class Watcher {
      constructor(fn) {
        this.fn = fn;
        this.update();
      }
      update() {
        currentWatcher = this;
        this.fn();
        currentWatcher = null;
      }
    }

基于 Proxy 的实现(Vue 3.x)

Vue 3.x 使用 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); // 触发更新
      return true;
    }
  });
}

function track(target, key) {
  // 收集依赖逻辑
}

function trigger(target, key) {
  // 触发更新逻辑
}

双向绑定的完整流程

  1. 模板编译
    Vue 模板编译时解析指令(如 v-model),生成渲染函数和更新函数。

  2. 数据响应式
    通过数据劫持或 Proxy 监听数据变化,建立依赖关系。

    vue 双向绑定实现

  3. 依赖更新
    数据变化时触发 setterProxy.set,通知 Watcher 更新视图。

  4. 视图更新
    Watcher 调用渲染函数更新 DOM,完成双向绑定。

示例代码

以下是一个简化的双向绑定实现:

// 数据劫持
function defineReactive(obj, key, val) {
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    get() {
      dep.depend();
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        val = newVal;
        dep.notify();
      }
    }
  });
}

// 依赖管理
class Dep {
  constructor() {
    this.subscribers = new Set();
  }
  depend() {
    if (currentWatcher) {
      this.subscribers.add(currentWatcher);
    }
  }
  notify() {
    this.subscribers.forEach(watcher => watcher.update());
  }
}

// Watcher
class Watcher {
  constructor(fn) {
    this.fn = fn;
    this.update();
  }
  update() {
    currentWatcher = this;
    this.fn();
    currentWatcher = null;
  }
}

// 测试
const data = { text: 'Hello' };
defineReactive(data, 'text', data.text);

new Watcher(() => {
  console.log('视图更新:', data.text);
});

data.text = 'World'; // 输出 "视图更新: World"

总结

  • Vue 2.x 使用 Object.defineProperty 实现数据劫持,但无法监听数组和深层对象。
  • Vue 3.x 使用 Proxy 解决上述问题,性能更好。
  • 双向绑定的核心是依赖收集和发布-订阅模式。

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

相关文章

vue实现数据绑定

vue实现数据绑定

Vue 数据绑定的实现方式 Vue.js 提供了多种数据绑定方式,主要包括双向绑定 (v-model)、单向绑定 ({{ }} 插值或 v-bind)、以及响应式数据管理。以下是具体实现方法: 双向…

实现vue动态绑定

实现vue动态绑定

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

vue实现双休绑定

vue实现双休绑定

Vue 实现双向绑定 Vue.js 通过 v-model 指令实现双向绑定,主要用于表单输入元素(如 <input>、<textarea>、<select>)与组件…

vue双向绑定实现

vue双向绑定实现

Vue 双向绑定实现原理 Vue 的双向绑定主要通过 v-model 指令实现,其核心是结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式。 数据劫持 Vue…

实现vue数据绑定

实现vue数据绑定

Vue数据绑定的实现方式 Vue.js通过数据劫持和发布-订阅模式实现数据绑定,核心是响应式系统。以下是主要实现方法: 双向数据绑定(v-model) <input v-model="mess…

实现vue数组双向绑定

实现vue数组双向绑定

Vue 数组双向绑定的实现方法 Vue 通过数据劫持和发布-订阅模式实现数据的双向绑定,但直接修改数组的某些方法(如索引赋值)无法触发视图更新。以下是实现数组双向绑定的几种方法: 使用 Vue.se…