当前位置:首页 > VUE

vue双向实现

2026-01-06 23:54:33VUE

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

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

数据劫持

Vue 2.x 使用 Object.defineProperty 监听对象属性的变化,Vue 3.x 改用 Proxy 实现更高效的数据劫持。当数据变化时,触发 setter 通知依赖更新。

// Vue 2.x 数据劫持示例
const data = { value: '' };
Object.defineProperty(data, 'value', {
  get() {
    return this._value;
  },
  set(newVal) {
    this._value = newVal;
    console.log('数据更新了');
  }
});

模板编译

Vue 将模板编译为渲染函数,解析 v-model 指令时,会为元素绑定 input 事件(或其他表单事件),并动态更新数据属性。

<input v-model="message">
<!-- 编译后等效于 -->
<input :value="message" @input="message = $event.target.value">

发布-订阅模式

通过 DepWatcher 实现依赖收集和更新。每个数据属性有一个 Dep 实例,当渲染时触发 getter 收集依赖(Watcher),数据变化时通过 setter 通知 Watcher 更新视图。

vue双向实现

自定义实现双向绑定

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

数据监听

使用 Object.defineProperty 监听输入框的值变化。

vue双向实现

function defineReactive(obj, key) {
  let value = obj[key];
  const dep = new Dep();

  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) dep.addSub(Dep.target);
      return value;
    },
    set(newVal) {
      if (newVal === value) return;
      value = newVal;
      dep.notify();
    }
  });
}

依赖管理

实现 DepWatcher 类管理依赖关系。

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;
    vm[exp]; // 触发 getter 收集依赖
    Dep.target = null;
  }
  update() {
    this.fn(this.vm[this.exp]);
  }
}

绑定指令

将输入框的 input 事件与数据属性关联。

function bindInput(input, vm, exp) {
  input.addEventListener('input', e => {
    vm[exp] = e.target.value;
  });
  new Watcher(vm, exp, value => {
    input.value = value;
  });
}

使用 Proxy 的实现(Vue 3 风格)

Vue 3 使用 Proxy 替代 Object.defineProperty,支持深层对象监听和数组变化。

function reactive(obj) {
  const dep = new Dep();
  return new Proxy(obj, {
    get(target, key) {
      if (Dep.target) dep.addSub(Dep.target);
      return target[key];
    },
    set(target, key, value) {
      if (target[key] === value) return true;
      target[key] = value;
      dep.notify();
      return true;
    }
  });
}

总结

  1. 数据劫持:通过 Object.definePropertyProxy 监听数据变化。
  2. 模板编译:将 v-model 转换为 :value@input 的语法糖。
  3. 依赖管理:利用 DepWatcher 实现数据与视图的自动同步。

通过以上机制,Vue 实现了数据变化自动更新视图、视图输入自动更新数据的双向绑定效果。

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

相关文章

vue实现滑动

vue实现滑动

Vue 实现滑动效果 使用 CSS 过渡和动画 通过 Vue 的 transition 组件结合 CSS 过渡或动画实现滑动效果。适用于简单的元素入场/离场滑动。 <template>…

vue前端实现搜索

vue前端实现搜索

实现搜索功能的基本方法 在Vue中实现搜索功能通常涉及以下几个关键步骤,结合数据绑定、计算属性和方法调用来动态过滤和显示结果。 数据绑定与输入处理 使用v-model双向绑定搜索输入框的值,监听用户…

vue实现点击页面切换

vue实现点击页面切换

实现点击页面切换功能 在Vue中实现点击页面切换功能,可以通过路由跳转或组件动态渲染两种方式完成。以下是具体实现方法: 使用Vue Router实现页面跳转 安装Vue Router后,在项目中配置…

vue实现安全免登录

vue实现安全免登录

Vue 实现安全免登录的方案 免登录功能通常通过持久化认证状态(如 Token)实现,但需兼顾安全性。以下是基于 Vue 的常见实现方案: 基于 Token 的免登录 登录成功后存储 Toke…

vue实现收起展开面板

vue实现收起展开面板

实现收起展开面板的方法 在Vue中实现收起展开面板功能可以通过多种方式完成,以下是几种常见的实现方法: 使用v-show或v-if控制显示隐藏 利用Vue的指令可以轻松实现面板的展开和收起:…

vue实现录音文件播放

vue实现录音文件播放

使用 Vue 实现录音文件播放 准备工作 确保项目中已安装必要的依赖,如 vue-audio-recorder 或原生 Web Audio API。录音文件播放通常涉及录音、存储和播放三个核心环节。…