当前位置:首页 > VUE

vue双向绑定实现简单

2026-01-07 04:16:37VUE

Vue 双向绑定的实现原理

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

数据劫持(响应式系统)

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

vue双向绑定实现简单

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 双向绑定的简单实现 双向绑定的核心是通过数据劫持结合发布-订阅模式实现。以下是简化版的实现步骤: 数据劫持(Object.defineProperty) 通过 Object.definePr…

vue样式绑定实现收藏

vue样式绑定实现收藏

Vue 样式绑定实现收藏功能 在 Vue 中,可以通过动态绑定样式来实现收藏功能,常见的方法是使用 v-bind:class 或 v-bind:style 来切换样式状态。 使用 v-bind:cl…

vue双向实现原理

vue双向实现原理

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

vue实现动态绑定样式

vue实现动态绑定样式

动态绑定样式的方法 在Vue中实现动态绑定样式主要通过v-bind:class和v-bind:style指令完成,支持对象语法、数组语法等多种灵活方式。 对象语法 通过对象可以动态切换class,对…

vue怎么实现数据绑定

vue怎么实现数据绑定

Vue 数据绑定的实现方式 Vue 的数据绑定主要通过指令和响应式系统实现,以下是核心方法: 双向数据绑定(v-model) v-model 指令用于表单元素与数据的双向绑定: <input…

vue底层实现双向绑定

vue底层实现双向绑定

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