当前位置:首页 > VUE

vue双向绑定实现函数

2026-02-24 04:55:07VUE

Vue 双向绑定实现原理

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

基于 Object.defineProperty 的实现(Vue 2.x)

  1. 数据劫持 通过 Object.defineProperty 劫持对象的属性,在属性被访问或修改时触发 getter 和 setter。

    function defineReactive(obj, key, val) {
      Object.defineProperty(obj, key, {
        get() {
          console.log(`获取 ${key}: ${val}`);
          return val;
        },
        set(newVal) {
          if (newVal !== val) {
            console.log(`设置 ${key}: ${newVal}`);
            val = newVal;
          }
        }
      });
    }
  2. 依赖收集 在 getter 中收集依赖(订阅者),在 setter 中通知依赖更新。

    class Dep {
      constructor() {
        this.subscribers = [];
      }
      depend() {
        if (target && !this.subscribers.includes(target)) {
          this.subscribers.push(target);
        }
      }
      notify() {
        this.subscribers.forEach(sub => sub());
      }
    }
    
    let target = null;
    function defineReactive(obj, key, val) {
      const dep = new Dep();
      Object.defineProperty(obj, key, {
        get() {
          dep.depend();
          return val;
        },
        set(newVal) {
          if (newVal !== val) {
            val = newVal;
            dep.notify();
          }
        }
      });
    }
  3. 观察者 创建一个观察者函数,用于更新视图。

    function watcher(fn) {
      target = fn;
      fn();
      target = null;
    }
  4. 完整示例

    const data = { text: 'hello' };
    defineReactive(data, 'text', data.text);
    watcher(() => {
      console.log('视图更新:', data.text);
    });
    data.text = 'world'; // 触发视图更新

基于 Proxy 的实现(Vue 3.x)

Vue 3.x 使用 Proxy 替代 Object.defineProperty,解决了无法监听数组变化和对象新增属性的问题。

  1. Proxy 数据劫持

    function reactive(obj) {
      const handler = {
        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;
        }
      };
      return new Proxy(obj, handler);
    }
  2. 依赖收集与触发

    const targetMap = new WeakMap();
    function track(target, key) {
      if (!activeEffect) 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(activeEffect);
    }
    
    function trigger(target, key) {
      const depsMap = targetMap.get(target);
      if (!depsMap) return;
      const dep = depsMap.get(key);
      if (dep) {
        dep.forEach(effect => effect());
      }
    }
    
    let activeEffect = null;
    function effect(fn) {
      activeEffect = fn;
      fn();
      activeEffect = null;
    }
  3. 完整示例

    const data = reactive({ text: 'hello' });
    effect(() => {
      console.log('视图更新:', data.text);
    });
    data.text = 'world'; // 触发视图更新

双向绑定的实现

双向绑定通常用于表单输入,结合 v-model 指令实现。

  1. 模板编译 将模板中的 v-model 解析为事件监听和属性绑定。

    <input v-model="message" />
    <!-- 等价于 -->
    <input :value="message" @input="message = $event.target.value" />
  2. 手动实现双向绑定

    vue双向绑定实现函数

    function bindInput(data, key, input) {
      input.value = data[key];
      input.addEventListener('input', (e) => {
        data[key] = e.target.value;
      });
    }
    
    const data = reactive({ message: '' });
    const input = document.querySelector('input');
    bindInput(data, 'message', input);
    effect(() => {
      console.log('数据更新:', data.message);
    });

总结

  • Vue 2.x 使用 Object.defineProperty 实现数据劫持,需要递归遍历对象属性。
  • Vue 3.x 使用 Proxy 实现数据劫持,能监听数组和对象新增属性。
  • 双向绑定是数据劫持与事件监听的结合,通过 v-model 简化操作。

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

相关文章

vue实现双向数据绑定的原理

vue实现双向数据绑定的原理

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

vue双向实现数据

vue双向实现数据

Vue 双向数据绑定的实现 Vue 的双向数据绑定主要通过 v-model 指令实现,它结合了 v-bind 和 v-on 的功能,能够同步表单输入和应用状态。 基本语法 在表单元素上使用 v-mo…

vue 实现循环绑定

vue 实现循环绑定

Vue 实现循环绑定的方法 在 Vue 中,可以通过 v-for 指令实现循环绑定,用于渲染列表或对象数据。以下是几种常见的实现方式: 数组循环绑定 使用 v-for 遍历数组,可以通过索引或直接获…

vue实现双向滚动

vue实现双向滚动

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

vue怎么实现双向

vue怎么实现双向

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

实现vue数组双向绑定

实现vue数组双向绑定

Vue 数组双向绑定的实现方法 Vue 通过数据劫持和发布-订阅模式实现数据的双向绑定,但直接修改数组的某些方法(如索引赋值)无法触发视图更新。以下是实现数组双向绑定的几种方法: 使用 Vue.se…