当前位置:首页 > 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实现下拉菜单可以通过动态绑定v-show或v-if控制菜单显示隐藏,结合事件监听(如@click或@mouseenter)触发状态切换。以下是两种常见实现方式: 方…

vue 实现手册

vue 实现手册

以下是关于 Vue.js 实现手册的整理内容,涵盖核心概念、实践方法和常见场景的解决方案: 核心概念与基础用法 Vue.js 是一个渐进式 JavaScript 框架,核心特点包括数据驱动视图和组件…

vue实现单词反转

vue实现单词反转

实现思路 在Vue中实现单词反转功能,可以通过多种方式完成。核心思路是利用JavaScript的字符串处理方法,将输入的单词或句子拆分为数组,反转数组后再拼接成字符串。 方法一:使用计算属性 通过计…

vue实现多级组件

vue实现多级组件

实现多级组件的基本结构 在Vue中实现多级组件通常涉及父子组件嵌套,通过props向下传递数据,通过$emit向上传递事件。多级组件的核心是递归或动态组件渲染。 <!-- 父组件 Parent…

vue实现图片搜索

vue实现图片搜索

Vue实现图片搜索功能 使用HTML5的File API获取图片 通过<input type="file">元素让用户选择图片文件,使用FileReader对象读取图片数据。 <t…

vue实现sql操作

vue实现sql操作

在Vue中实现SQL操作通常需要结合后端服务或本地数据库技术,因为前端JavaScript无法直接连接SQL数据库。以下是几种常见的实现方式: 通过API与后端交互 Vue前端通过HTTP请求(如a…