当前位置:首页 > VUE

vue双向绑定实现简单

2026-01-07 04:16:37VUE

Vue 双向绑定的实现原理

Vue 的双向绑定是通过 v-model 指令实现的,其核心是基于数据劫持和发布-订阅模式。以下是一个简化版的实现示例:

数据劫持(响应式系统)

利用 Object.defineProperty 或 ES6 的 Proxy 监听数据变化:

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)

class Watcher {
  constructor(vm, exp, cb) {
    this.vm = vm;
    this.exp = exp;
    this.cb = cb;
    this.value = this.get(); // 触发属性 getter 收集依赖
  }
  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);
    }
  }
}

实现 v-model 指令

class Vue {
  constructor(options) {
    this.$data = options.data;
    observe(this.$data);
    this.$compile(options.el);
  }

  $compile(el) {
    const element = document.querySelector(el);
    this.compileElement(element);
  }

  compileElement(node) {
    Array.from(node.attributes).forEach(attr => {
      if (attr.name === 'v-model') {
        const exp = attr.value;
        node.addEventListener('input', e => {
          this.$data[exp] = e.target.value; // 触发 setter
        });
        new Watcher(this, exp, value => {
          node.value = value; // 更新视图
        });
      }
    });
    // 递归处理子节点
    node.childNodes.forEach(child => {
      if (child.nodeType === 1) this.compileElement(child);
    });
  }
}

使用示例

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

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

关键点说明

  • 数据劫持:通过 Object.defineProperty 将数据转为响应式
  • 依赖收集:在 getter 中收集依赖的 Watcher
  • 派发更新:在 setter 中通知所有 Watcher 更新视图
  • 指令解析:编译模板时处理 v-model 指令,绑定事件和 Watcher

现代 Vue 3 使用 Proxy 替代 Object.defineProperty,解决了无法检测新增属性的限制,但核心原理仍保持一致。

vue双向绑定实现简单

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

相关文章

vue实现事件绑定的是

vue实现事件绑定的是

Vue 事件绑定实现方式 Vue 通过 v-on 指令或 @ 简写实现事件绑定,支持多种事件处理方式。 基础语法 <button v-on:click="handleClick">点击事…

实现vue双向绑定

实现vue双向绑定

Vue双向绑定的实现原理 Vue的双向绑定主要通过数据劫持结合发布-订阅模式实现。核心是利用Object.defineProperty()或ES6的Proxy来劫持各个属性的getter和setter…

vue双向实现数据

vue双向实现数据

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

vue实现绑定herf

vue实现绑定herf

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