当前位置:首页 > 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 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 的语法糖。

// 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);
    }
  });
}

vue 双向绑定实现

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

相关文章

uniapp怎么给标签绑定颜色

uniapp怎么给标签绑定颜色

在 uniapp 中给标签绑定颜色 在 uniapp 中,可以通过动态绑定样式或类名的方式为标签设置颜色。以下是几种常见的方法: 动态绑定内联样式 使用 :style 绑定动态样式对象,直接在标签…

jquery绑定事件

jquery绑定事件

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

vue实现数据绑定

vue实现数据绑定

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

php实现双向队列

php实现双向队列

PHP 实现双向队列的方法 双向队列(Deque,Double-ended Queue)是一种允许在队列两端进行插入和删除操作的数据结构。PHP 中可以通过数组或 SplDoublyLinkedLis…

Vue数据绑定实现

Vue数据绑定实现

Vue 数据绑定的核心机制 Vue 的数据绑定基于响应式系统,通过 Object.defineProperty 或 Proxy 实现。当数据变化时,视图自动更新。 双向绑定的实现方式 v-model…