当前位置:首页 > 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 实例。

vue 双向绑定实现

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 的结合:

vue 双向绑定实现

<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);
    }
  }
};

实现简易双向绑定

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

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.js 通过数据绑定机制实现数据和页面的同步更新,主要依赖响应式系统和模板语法。以下是几种常见的绑定方式: 双向绑定 (v-model) 使用 v-model…

ie实现vue动态绑定

ie实现vue动态绑定

在IE浏览器中实现Vue动态绑定的方法 IE浏览器(尤其是IE11及以下版本)对ES6语法和现代JavaScript特性的支持有限,导致Vue.js的部分功能(如动态绑定)可能无法直接运行。以下是针对…

vue双向绑定实现案例

vue双向绑定实现案例

Vue 双向绑定实现案例 Vue 的双向绑定通过 v-model 指令实现,结合了数据绑定和事件监听。以下是几种常见场景的实现案例: 基础输入框绑定 <template> <i…

vue实现双向绑定代码

vue实现双向绑定代码

Vue 双向绑定实现代码 Vue 的双向绑定主要通过 v-model 指令实现,它结合了 v-bind(属性绑定)和 v-on(事件监听)的功能。以下是几种常见场景的实现代码: 基础输入框绑定 &l…

react实现双向绑定

react实现双向绑定

React 实现双向绑定的方法 React 本身是单向数据流框架,但可以通过以下方式模拟双向绑定效果: 受控组件方式 通过 value 和 onChange 实现表单元素与状态的同步: funct…

react实现双向绑定原理

react实现双向绑定原理

React 双向绑定原理 React 本身是单向数据流的设计理念,但可以通过特定方式实现类似双向绑定的效果。以下是常见的实现方法: 受控组件方式 通过 value 和 onChange 属性控制表单…