当前位置:首页 > 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 简化操作。

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

相关文章

react如何绑定事件

react如何绑定事件

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

vue 双向实现原理

vue 双向实现原理

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

vue怎么实现绑定

vue怎么实现绑定

数据绑定基础 Vue 通过 v-bind 指令实现单向数据绑定(数据从模型到视图),语法为 v-bind:属性="数据" 或简写为 :属性="数据"。例如绑定 src 属性: <img :…

vue实现数据双向

vue实现数据双向

在Vue中实现数据双向绑定主要依靠v-model指令,它结合了属性绑定和事件监听,适用于表单元素或自定义组件。以下是具体实现方式: 基础表单元素的双向绑定 对于原生表单元素(如input、texta…

vue实现数组双向绑定

vue实现数组双向绑定

实现数组双向绑定的方法 在Vue中,实现数组的双向绑定通常需要结合v-model指令或自定义事件处理。以下是几种常见的方法: 使用v-model绑定数组 Vue的v-model指令默认支持表单元素的…

vue 双向绑定 实现原理

vue 双向绑定 实现原理

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