当前位置:首页 > VUE

vue 双向绑定实现

2026-03-09 02:53:16VUE

Vue 双向绑定的实现原理

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

数据劫持(响应式系统)

通过 Object.definePropertyProxy 拦截数据的读写操作,在数据变化时触发更新。

// Vue 2.x 使用 Object.defineProperty
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        val = newVal;
        // 触发更新
        dep.notify();
      }
    }
  });
}

// Vue 3.x 使用 Proxy
const reactive = (target) => {
  return new Proxy(target, {
    get(target, key, receiver) {
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      // 触发更新
      trigger(target, key);
      return result;
    }
  });
};

依赖收集(发布-订阅模式)

每个响应式数据维护一个依赖收集器(Dep),用于存储所有依赖该数据的 Watcher 实例。

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

class Watcher {
  constructor(vm, exp, fn) {
    this.vm = vm;
    this.exp = exp;
    this.fn = fn;
    Dep.target = this;
    // 触发 getter 以收集依赖
    this.vm[this.exp];
    Dep.target = null;
  }
  update() {
    this.fn();
  }
}

模板编译

Vue 通过编译器将模板解析为渲染函数,在解析过程中识别指令(如 v-model)并生成对应的数据绑定代码。

// 简化的 v-model 编译逻辑
function compileModel(el, dir, _warn) {
  const { value, modifiers } = dir;
  // 生成代码,将输入事件与数据更新绑定
  addHandler(el, 'input', `$event => { ${value} = $event.target.value }`);
}

双向绑定实现(v-model)

v-model 是语法糖,本质是 :value@input 的结合:

<input v-model="message">
<!-- 等价于 -->
<input :value="message" @input="message = $event.target.value">

对于组件,v-model 默认使用 value prop 和 input 事件,可通过 model 选项自定义:

// 组件内
export default {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: ['checked'],
  methods: {
    handleChange(e) {
      this.$emit('change', e.target.value);
    }
  }
};

实现简易双向绑定

以下是一个简化版的实现示例:

vue 双向绑定实现

class Vue {
  constructor(options) {
    this.$data = options.data;
    this.observe(this.$data);
    this.compile(options.el);
  }
  observe(data) {
    Object.keys(data).forEach(key => {
      let value = data[key];
      const dep = new Dep();
      Object.defineProperty(data, key, {
        get() {
          Dep.target && dep.addSub(Dep.target);
          return value;
        },
        set(newVal) {
          if (newVal !== value) {
            value = newVal;
            dep.notify();
          }
        }
      });
    });
  }
  compile(el) {
    const element = document.querySelector(el);
    Array.from(element.children).forEach(node => {
      if (node.hasAttribute('v-model')) {
        const key = node.getAttribute('v-model');
        node.value = this.$data[key];
        new Watcher(this, key, () => {
          node.value = this.$data[key];
        });
        node.addEventListener('input', () => {
          this.$data[key] = node.value;
        });
      }
    });
  }
}

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

相关文章

Vue数据绑定实现

Vue数据绑定实现

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

怎么实现vue双向绑定

怎么实现vue双向绑定

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

vue实现双向绑定模拟

vue实现双向绑定模拟

Vue 双向绑定模拟实现 Vue 的双向绑定核心是通过数据劫持结合发布-订阅模式实现。以下是一个简化版的模拟实现: 数据劫持(Object.defineProperty) 通过 Object.def…

vue动态绑定的实现

vue动态绑定的实现

Vue 动态绑定的实现方法 Vue 的动态绑定主要通过 v-bind 指令或简写 : 实现,用于动态地将数据绑定到 HTML 元素的属性上。以下是几种常见的动态绑定实现方式: 动态绑定属性 <…

vue实现style双向绑定

vue实现style双向绑定

Vue 实现 Style 双向绑定 在 Vue 中实现 style 的双向绑定可以通过动态绑定 :style 属性来实现。Vue 提供了多种方式动态绑定样式,包括对象语法和数组语法。 对象语法 通过…

react实现vue双向绑定

react实现vue双向绑定

在React中实现类似Vue的双向绑定功能,可以通过以下方法实现。React本身是单向数据流,但结合状态管理和事件处理可以模拟双向绑定效果。 使用受控组件 通过value和onChange实现表单元…