当前位置:首页 > VUE

vue双向绑定实现简单

2026-02-09 17:29:43VUE

Vue 双向绑定的实现原理

Vue 的双向绑定是通过数据劫持结合发布者-订阅者模式实现的,主要依赖 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)来监听数据变化。

使用 Object.defineProperty 实现

Vue 2.x 使用 Object.defineProperty 劫持对象的属性,通过 getter 和 setter 实现数据监听。

function defineReactive(obj, key, val) {
  const dep = new Dep(); // 依赖收集器

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      if (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;

使用 Proxy 实现

Vue 3.x 改用 Proxy 实现数据劫持,可以监听整个对象而无需递归遍历。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      track(target, key); // 收集依赖
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

const targetMap = new WeakMap();

function track(target, key) {
  if (!Dep.target) return;
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }
  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(Dep.target);
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  const dep = depsMap.get(key);
  if (dep) {
    dep.forEach(effect => effect());
  }
}

实现简单的双向绑定

结合 v-model 指令,可以实现一个简单的双向绑定示例。

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

<script>
  function compile(el, vm) {
    el.querySelectorAll('[v-model]').forEach(node => {
      const key = node.getAttribute('v-model');
      node.value = vm.data[key];
      node.addEventListener('input', () => {
        vm.data[key] = node.value;
      });
    });

    el.querySelectorAll('*').forEach(node => {
      if (node.textContent.includes('{{')) {
        const key = node.textContent.match(/\{\{(.*?)\}\}/)[1].trim();
        node.textContent = vm.data[key];
        new Watcher(vm, key, val => {
          node.textContent = val;
        });
      }
    });
  }

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

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

关键点总结

  • 数据劫持:通过 Object.definePropertyProxy 监听数据变化。
  • 依赖收集:在 getter 中收集依赖,在 setter 中触发更新。
  • 模板编译:解析模板中的指令和插值表达式,建立数据与视图的关联。
  • 更新机制:数据变化时通知所有依赖的视图更新。

vue双向绑定实现简单

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

相关文章

react如何绑定事件

react如何绑定事件

React 事件绑定方法 在 React 中绑定事件有多种方式,以下是常见的几种方法: 使用 onClick 或其他事件属性直接绑定 <button onClick={() => co…

Vue数据绑定实现

Vue数据绑定实现

Vue 数据绑定的核心机制 Vue 的数据绑定基于响应式系统,通过 Object.defineProperty 或 Proxy 实现。当数据变化时,视图自动更新。 双向绑定的实现方式 v-mode…

vue实现事件绑定

vue实现事件绑定

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

vue双向绑定实现方式

vue双向绑定实现方式

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

vue简单实现双向绑定

vue简单实现双向绑定

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

vue绑定图片实现默认

vue绑定图片实现默认

vue绑定图片实现默认的方法 在Vue中绑定图片并设置默认图片,可以通过多种方式实现。以下是几种常见的方法: 使用v-bind绑定图片路径 在模板中使用v-bind指令绑定图片路径,同时设置默认图…