当前位置:首页 > 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 实现搜索功能 在 Vue 中实现搜索功能通常涉及数据绑定、事件监听和过滤逻辑。以下是几种常见的实现方式: 使用计算属性过滤列表 <template> <div>…

vue实现密码框的包

vue实现密码框的包

Vue 密码框实现方案 在 Vue 中实现密码框功能,可以通过原生 HTML 结合 Vue 指令或使用第三方组件库完成。以下是几种常见方案: 原生 HTML + Vue 双向绑定 <t…

vue实现高亮

vue实现高亮

Vue 实现文本高亮的方法 在 Vue 中实现文本高亮可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 v-html 指令 通过 v-html 指令可以动态插入 HTML 内容,将需要高…

vue diff实现

vue diff实现

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

vue实现开关

vue实现开关

Vue 实现开关组件的方法 使用原生HTML和Vue数据绑定 通过v-model绑定复选框的checked状态,结合CSS样式实现开关效果: <template> <label…

vue实现curd

vue实现curd

Vue实现CRUD操作 初始化Vue项目 使用Vue CLI创建新项目,安装必要依赖如axios用于HTTP请求 vue create crud-demo cd crud-demo npm inst…