当前位置:首页 > VUE

vue 双向绑定实现

2026-02-17 14:25:12VUE

Vue 双向绑定的实现原理

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

数据劫持

Vue 2.x 使用 Object.defineProperty 劫持对象的属性访问和修改。通过定义属性的 gettersetter,在数据变化时触发更新。

let data = { name: 'Vue' };
Object.defineProperty(data, 'name', {
  get() {
    console.log('获取数据');
    return value;
  },
  set(newValue) {
    console.log('更新数据');
    value = newValue;
    // 触发视图更新
  }
});

Vue 3.x 使用 Proxy 代理整个对象,可以监听动态添加的属性,性能更好。

let data = { name: 'Vue' };
let proxy = new Proxy(data, {
  get(target, key) {
    console.log('获取数据');
    return target[key];
  },
  set(target, key, value) {
    console.log('更新数据');
    target[key] = value;
    // 触发视图更新
    return true;
  }
});

依赖收集

每个响应式属性都有一个依赖收集器(Dep),用于存储依赖该属性的 Watcher 实例。当属性被访问时,当前 Watcher 会被添加到 Dep 中。

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

发布-订阅模式

Watcher 是订阅者,当数据变化时,Dep 会通知所有 Watcher 更新视图。Watcher 在初始化时会触发属性的 getter,从而完成依赖收集。

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    Dep.target = this;
    this.value = vm[key]; // 触发 getter
    Dep.target = null;
  }
  update() {
    const newValue = this.vm[this.key];
    if (newValue !== this.value) {
      this.value = newValue;
      this.cb(newValue);
    }
  }
}

模板编译

Vue 的模板编译器会将模板中的指令(如 v-model)解析为渲染函数。对于 v-model,会生成对应的数据绑定和事件监听代码。

<input v-model="message">

编译后的代码类似于:

input.addEventListener('input', function(e) {
  vm.message = e.target.value;
});

实现双向绑定的步骤

  1. 初始化时对数据进行响应式处理,劫持属性的 gettersetter
  2. 解析模板,为每个指令创建对应的 Watcher,并在首次渲染时触发依赖收集。
  3. 当数据变化时,触发 setter,通知 Dep 调用所有 Watcher 的 update 方法更新视图。
  4. 对于 v-model,额外监听表单元素的输入事件,将用户输入同步到数据。

示例代码

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

class Vue {
  constructor(options) {
    this.$data = options.data;
    this.observe(this.$data);
    this.compile(options.el);
  }
  observe(data) {
    Object.keys(data).forEach(key => {
      let value = data[key];
      const dep = new Dep();
      Object.defineProperty(data, key, {
        get() {
          if (Dep.target) dep.addSub(Dep.target);
          return value;
        },
        set(newValue) {
          if (newValue !== value) {
            value = newValue;
            dep.notify();
          }
        }
      });
    });
  }
  compile(el) {
    const element = document.querySelector(el);
    this.compileNode(element);
  }
  compileNode(element) {
    element.childNodes.forEach(node => {
      if (node.nodeType === 1) {
        if (node.hasAttribute('v-model')) {
          const key = node.getAttribute('v-model');
          node.addEventListener('input', e => {
            this.$data[key] = e.target.value;
          });
          new Watcher(this, key, value => {
            node.value = value;
          });
        }
      }
    });
  }
}

通过以上机制,Vue 实现了数据与视图的双向绑定,使得数据变化时视图自动更新,用户输入时数据自动同步。

vue 双向绑定实现

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

相关文章

vue实现事件绑定的是

vue实现事件绑定的是

Vue 事件绑定实现方式 Vue 通过 v-on 指令实现事件绑定,语法为 v-on:事件名="处理方法" 或简写为 @事件名="处理方法"。以下是具体实现方法和示例: 基础事件绑定 <bu…

vue数据实现双向绑定

vue数据实现双向绑定

Vue 数据双向绑定的实现原理 Vue 的数据双向绑定主要通过 v-model 指令实现,结合了数据绑定和事件监听。以下是核心实现方式: 使用 v-model 指令 v-model 是语法糖,自动绑…

php实现双向队列

php实现双向队列

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

vue双向实现原理

vue双向实现原理

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

vue实现数据双向

vue实现数据双向

在Vue中实现数据双向绑定主要依靠v-model指令,它结合了属性绑定和事件监听,适用于表单元素或自定义组件。以下是具体实现方式: 基础表单元素的双向绑定 对于原生表单元素(如input、texta…

vue双向绑定实现方式

vue双向绑定实现方式

Vue 双向绑定的实现方式 Vue 的双向绑定主要通过 v-model 指令实现,结合数据劫持和发布-订阅模式完成数据与视图的同步更新。以下是核心实现原理及方式: 数据劫持(响应式原理) Vue 使…