当前位置:首页 > VUE

vue双向实现

2026-01-11 21:37:32VUE

Vue 双向绑定的实现原理

Vue 的双向绑定主要通过 v-model 指令实现,底层结合了数据劫持(Object.definePropertyProxy)和发布-订阅模式。以下是核心实现机制:

数据劫持

Vue 2.x 使用 Object.defineProperty 劫持对象的属性访问和修改,Vue 3.x 改用 Proxy 实现更高效的数据监听。

Vue 2.x 示例:

const data = { text: '' };
Object.defineProperty(data, 'text', {
  get() {
    return this._text;
  },
  set(newVal) {
    this._text = newVal;
    console.log('数据更新了');
  }
});

Vue 3.x 示例:

vue双向实现

const data = { text: '' };
const proxy = new Proxy(data, {
  get(target, key) {
    return target[key];
  },
  set(target, key, value) {
    target[key] = value;
    console.log('数据更新了');
    return true;
  }
});

发布-订阅模式

通过 Dep(依赖收集器)和 Watcher(观察者)实现数据变化时的视图更新:

class Dep {
  constructor() {
    this.subscribers = [];
  }
  depend() {
    if (Watcher.target) {
      this.subscribers.push(Watcher.target);
    }
  }
  notify() {
    this.subscribers.forEach(sub => sub.update());
  }
}

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    Watcher.target = this;
    this.vm[this.key]; // 触发 getter 收集依赖
    Watcher.target = null;
  }
  update() {
    this.cb.call(this.vm, this.vm[this.key]);
  }
}

v-model 的实现

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

vue双向实现

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

自定义双向绑定组件

通过 model 选项和 $emit 实现自定义组件的双向绑定:

子组件:

export default {
  model: {
    prop: 'value',
    event: 'change'
  },
  props: ['value'],
  methods: {
    handleInput(e) {
      this.$emit('change', e.target.value);
    }
  }
}

父组件使用:

<custom-input v-model="text"></custom-input>

注意事项

  • Vue 2.x 中 Object.defineProperty 无法检测数组下标变化,需通过 Vue.set 或数组方法触发更新。
  • Vue 3.x 的 Proxy 支持深层监听,但需注意性能开销。
  • 复杂场景可结合 .sync 修饰符或 v-bind.sync 实现多属性双向绑定。

标签: 双向vue
分享给朋友:

相关文章

vue实现扫描二维码

vue实现扫描二维码

实现 Vue 扫描二维码功能 在 Vue 中实现扫描二维码功能,可以通过第三方库或原生 API 完成。以下是两种常见方法: 使用 vue-qrcode-reader 库 vue-qrcode-re…

vue实现文件下载

vue实现文件下载

使用 a 标签下载文件 通过动态创建 a 标签并触发点击事件实现文件下载。适用于直接下载服务器上的静态文件或 Blob 数据。 downloadFile(url, fileName) { c…

vue实现滚动中断

vue实现滚动中断

Vue 实现滚动中断的方法 在 Vue 中实现滚动中断通常涉及监听滚动事件,并在特定条件下阻止默认行为或停止滚动。以下是几种常见方法: 监听滚动事件并阻止默认行为 通过 @scroll 或 @whe…

vue实现选择季度

vue实现选择季度

Vue 实现选择季度的几种方法 使用下拉选择框(Select) 在 Vue 中可以通过 v-model 绑定一个下拉选择框来实现季度选择。数据可以预先定义为一个包含季度选项的数组。 <…

vue怎么实现动画

vue怎么实现动画

Vue 动画实现方法 Vue 提供了多种方式实现动画效果,包括内置过渡系统、第三方库集成以及 CSS 动画。以下是常见实现方法: 使用 Vue 过渡系统 通过 <transition>…

vue如何实现放大缩小

vue如何实现放大缩小

Vue实现放大缩小功能的方法 在Vue中实现元素的放大缩小功能,可以通过CSS变换、第三方库或直接操作DOM样式来实现。以下是几种常见的方法: 使用CSS transform属性 通过绑定Vue的…