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

vue实现app

Vue 实现 App 的常见方法 使用 Vue 开发移动端 App 主要有两种主流方案:混合开发(Hybrid)和原生渲染。以下是具体实现方式和工具链: 混合开发方案(WebView 嵌入) 通过…

vue实现图集

vue实现图集

Vue 实现图集的方法 在 Vue 中实现图集功能可以通过多种方式完成,以下是一些常见的方法和实现步骤。 使用第三方库(如 vue-image-lightbox) 安装 vue-image-ligh…

vue实现翻译

vue实现翻译

Vue 实现翻译功能的方法 使用 i18n 插件实现多语言切换 安装 vue-i18n 插件: npm install vue-i18n 创建语言资源文件(如 en.json 和 zh.json)…

vue实现博客

vue实现博客

Vue 实现博客的基本步骤 使用 Vue.js 实现一个博客系统可以分为前端和后端两部分。以下是基于 Vue 的前端实现方案,后端可以选择 Node.js、Django 或其他框架。 项目初始化 使…

vue 实现注册

vue 实现注册

Vue 实现注册功能 注册功能通常包括表单验证、数据提交和用户反馈。以下是实现注册功能的步骤: 1. 创建注册表单组件 在 Vue 项目中创建一个注册表单组件,包含用户名、邮箱、密码等输入字段。…

vue diff实现

vue diff实现

Vue Diff 算法实现原理 Vue 的虚拟 DOM Diff 算法(即 patch 过程)是其高效渲染的核心,主要通过对比新旧虚拟节点的差异,最小化 DOM 操作。以下是关键实现要点: 同层级比…