当前位置:首页 > 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(); // 通知更新
    }
  });
}

依赖收集系统

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

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

编译器实现

简单模板解析:

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实现双向绑定模拟

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

相关文章

vue实现双向

vue实现双向

Vue 实现双向绑定的方法 Vue 主要通过 v-model 指令实现双向绑定,适用于表单元素或自定义组件。以下是几种常见实现方式: 表单元素的双向绑定 在表单元素(如 input、textarea…

jquery事件绑定

jquery事件绑定

jQuery 事件绑定的基本方法 使用 on() 方法绑定事件是最推荐的方式,兼容性强且支持动态元素。语法如下: $(selector).on(eventName, handlerFunction)…

vue如何实现绑定

vue如何实现绑定

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

vue实现数据双向

vue实现数据双向

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

vue怎么实现双向

vue怎么实现双向

Vue 双向绑定的实现方式 Vue 中实现双向绑定的核心机制是 v-model 指令,它结合了属性绑定和事件监听,适用于表单元素或自定义组件。 表单元素的双向绑定 在原生表单元素(如 input、s…

vue实现事件绑定

vue实现事件绑定

Vue 事件绑定实现方法 Vue 提供了多种方式实现事件绑定,以下是常用方法: v-on 指令 使用 v-on 指令绑定事件监听器,语法为 v-on:event="handler" 或简写为 @ev…