当前位置:首页 > VUE

vue实现双向绑定模拟

2026-02-22 04:16:42VUE

Vue 双向绑定模拟实现

双向绑定是 Vue 的核心特性之一,其本质是通过数据劫持结合发布订阅模式实现的。以下是一个简化的模拟实现:

数据劫持(响应式原理)

通过 Object.definePropertyProxy 拦截对象的属性访问和修改:

function observe(data) {
  if (!data || typeof data !== 'object') return;
  Object.keys(data).forEach(key => {
    defineReactive(data, key, data[key]);
  });
}

function defineReactive(obj, key, val) {
  observe(val); // 递归处理嵌套对象
  const dep = new Dep(); // 每个属性对应一个依赖管理器

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      Dep.target && dep.addSub(Dep.target); // 收集依赖
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // 通知更新
    }
  });
}

依赖收集系统

实现一个简单的依赖管理器:

vue实现双向绑定模拟

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}
Dep.target = null; // 全局唯一Watcher

观察者(Watcher)

每个表达式或指令对应一个 Watcher 实例:

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

编译器实现

简单模板解析:

vue实现双向绑定模拟

function compile(node, vm) {
  if (node.nodeType === 1) { // 元素节点
    Array.from(node.attributes).forEach(attr => {
      if (attr.name.startsWith('v-')) {
        const exp = attr.value;
        if (attr.name === 'v-model') {
          node.addEventListener('input', e => {
            vm[exp] = e.target.value;
          });
          new Watcher(vm, exp, value => {
            node.value = value;
          });
        }
      }
    });
  } else if (node.nodeType === 3) { // 文本节点
    const reg = /\{\{(.*)\}\}/;
    if (reg.test(node.textContent)) {
      const exp = RegExp.$1.trim();
      new Watcher(vm, exp, value => {
        node.textContent = value;
      });
    }
  }
}

完整整合

创建 Vue 类整合上述功能:

class Vue {
  constructor(options) {
    this.$options = options;
    this._data = options.data;
    observe(this._data);
    Object.keys(this._data).forEach(key => {
      this._proxy(key);
    });
    compile(document.querySelector(options.el), this);
  }

  _proxy(key) {
    Object.defineProperty(this, key, {
      enumerable: true,
      configurable: true,
      get: () => this._data[key],
      set: val => this._data[key] = val
    });
  }
}

使用示例

<div id="app">
  <input v-model="message">
  <p>{{ message }}</p>
</div>

<script>
const vm = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
});
</script>

现代实现改进

对于 Vue 3.0+ 的实现,主要改进点:

  • 使用 Proxy 代替 Object.defineProperty
  • 引入 effectreactive 等组合式API
  • 优化依赖收集机制
  • 支持更多数据类型(如 Map/Set)

这种实现方式展示了 Vue 双向绑定的核心思想,实际实现还包含虚拟DOM、组件系统等更多复杂功能。

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

相关文章

vue实现绑定herf

vue实现绑定herf

Vue 中实现绑定 href 的方法 在 Vue 中绑定 href 属性可以通过多种方式实现,以下是几种常见的方法: 使用 v-bind 或简写 : 通过 v-bind 或简写 : 动态绑定 hre…

实现vue双向绑定

实现vue双向绑定

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

vue如何实现绑定

vue如何实现绑定

数据绑定基础 Vue 通过 v-bind 指令实现动态绑定 HTML 属性或组件 prop。基本语法为 v-bind:属性名="表达式",简写为 :属性名="表达式"。例如绑定 class 或 sty…

vue实现数组双向绑定

vue实现数组双向绑定

实现数组双向绑定的方法 在Vue中,实现数组的双向绑定通常需要结合v-model指令或自定义事件处理。以下是几种常见的方法: 使用v-model绑定数组 Vue的v-model指令默认支持表单元素的…

vue简单实现双向绑定

vue简单实现双向绑定

Vue 双向绑定的简单实现 Vue 的双向绑定核心是通过 v-model 指令实现的,它结合了 v-bind 和 v-on 的功能。以下是一个简单的实现方式: 模板部分 <template&…

vue实现数组元素绑定

vue实现数组元素绑定

Vue 数组元素绑定方法 在 Vue 中实现数组元素绑定需要特别注意响应式更新的问题。以下是几种常见实现方式: 直接索引绑定(不推荐) 直接通过索引修改数组元素不会触发视图更新: this.arr…