当前位置:首页 > 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 指令,可以实现一个简单的双向绑定示例。

vue双向绑定实现简单

<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实现事件绑定的是

vue实现事件绑定的是

Vue 事件绑定实现方式 Vue 通过 v-on 指令实现事件绑定,语法为 v-on:事件名="处理方法" 或简写为 @事件名="处理方法"。以下是具体实现方法和示例: 基础事件绑定 <bu…

vue如何实现绑定

vue如何实现绑定

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

vue实现双向滚动

vue实现双向滚动

实现双向滚动的 Vue 方法 双向滚动通常指两个关联的滚动区域(如表格的头部和内容部分)同步滚动。以下是几种实现方式: 使用事件监听和 scroll 方法 通过监听一个滚动区域的 scrol…

vue实现事件绑定

vue实现事件绑定

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

vue双向数据绑定实现

vue双向数据绑定实现

双向数据绑定的概念 双向数据绑定是指视图(View)与模型(Model)之间的双向同步。当数据发生变化时,视图自动更新;当用户操作视图时,数据也会自动更新。Vue 通过 v-model 指令实现双向数…

vue怎么实现input绑定

vue怎么实现input绑定

实现 Vue 中 input 绑定的方法 使用 v-model 指令实现双向绑定 v-model 是 Vue 提供的语法糖,用于实现表单元素与数据的双向绑定。它会根据输入框类型自动选取正确的方式更新数…