当前位置: 首页 > article >正文

vue的双向绑定是怎么实现的

Vue.js 的双向绑定是通过 数据劫持(Data Observation) 和 发布-订阅模式(Publish-Subscribe Pattern) 实现的。具体来说,Vue 使用了以下核心技术:

  1. 数据劫持:通过 Object.defineProperty 或 Proxy 监听数据的变化。

  2. 依赖收集:在数据读取时收集依赖(Watcher)。

  3. 派发更新:在数据变化时通知依赖更新。

以下是 Vue 双向绑定的实现原理和详细步骤:


1. 数据劫持

Vue 通过数据劫持监听数据的变化。在 Vue 2.x 中,使用 Object.defineProperty;在 Vue 3.x 中,使用 Proxy

(1)Vue 2.x:Object.defineProperty
  • 原理:通过 Object.defineProperty 将对象的属性转换为 getter 和 setter

  • 示例

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`设置 ${key}: ${newVal}`);
        val = newVal;
      }
    },
  });
}

const data = {};
defineReactive(data, 'message', 'Hello');
console.log(data.message); // 读取 message: Hello
data.message = 'World';    // 设置 message: World
(2)Vue 3.x:Proxy
  • 原理:通过 Proxy 监听整个对象的变化,支持动态添加属性。

  • 示例

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      console.log(`读取 ${key}: ${target[key]}`);
      return target[key];
    },
    set(target, key, newVal) {
      if (target[key] !== newVal) {
        console.log(`设置 ${key}: ${newVal}`);
        target[key] = newVal;
      }
      return true;
    },
  });
}

const data = reactive({ message: 'Hello' });
console.log(data.message); // 读取 message: Hello
data.message = 'World';    // 设置 message: World

2. 依赖收集

Vue 在数据读取时收集依赖(Watcher),在数据变化时通知依赖更新。

(1)Watcher
  • 作用:Watcher 是 Vue 中的观察者,负责监听数据的变化并执行回调。

  • 示例

class Watcher {
  constructor(vm, key, updateFn) {
    this.vm = vm;
    this.key = key;
    this.updateFn = updateFn;

    // 触发 getter,收集依赖
    Dep.target = this;
    this.vm[this.key];
    Dep.target = null;
  }

  update() {
    this.updateFn.call(this.vm, this.vm[this.key]);
  }
}
(2)Dep
  • 作用:Dep 是依赖管理器,负责存储 Watcher 并通知更新。

  • 示例

class Dep {
  constructor() {
    this.subscribers = [];
  }

  depend() {
    if (Dep.target) {
      this.subscribers.push(Dep.target);
    }
  }

  notify() {
    this.subscribers.forEach(sub => sub.update());
  }
}
(3)结合数据劫持和依赖收集
  • 在 getter 中收集依赖,在 setter 中派发更新。

  • 示例

function defineReactive(obj, key, val) {
  const dep = new Dep();

  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend(); // 收集依赖
      }
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        val = newVal;
        dep.notify(); // 派发更新
      }
    },
  });
}

3. 派发更新

当数据变化时,Vue 会通知所有依赖(Watcher)更新视图。

示例:
const data = {};
defineReactive(data, 'message', 'Hello');

new Watcher(data, 'message', (value) => {
  console.log(`视图更新: ${value}`);
});

data.message = 'World'; // 设置 message: World -> 视图更新: World

4. 双向绑定的实现

Vue 的双向绑定是通过 v-model 指令实现的。v-model 是 v-bind 和 v-on 的语法糖。

(1)v-model 的原理
  • v-bind:将数据绑定到视图。

  • v-on:监听视图的变化并更新数据。

(2)示例
<input v-model="message" />

 等价于:

<input :value="message" @input="message = $event.target.value" />

 

5. Vue 3.x 的改进

在 Vue 3.x 中,使用 Proxy 替代 Object.defineProperty,解决了以下问题:

  • 动态添加属性Proxy 可以监听动态添加的属性。

  • 性能优化Proxy 的性能优于 Object.defineProperty


6. 总结

Vue 的双向绑定是通过以下步骤实现的:

  1. 数据劫持:使用 Object.defineProperty 或 Proxy 监听数据的变化。

  2. 依赖收集:在数据读取时收集依赖(Watcher)。

  3. 派发更新:在数据变化时通知依赖更新。

  4. 双向绑定:通过 v-model 实现视图和数据的双向同步。

通过这种机制,Vue 实现了高效的双向绑定,使得开发者可以专注于业务逻辑,而无需手动操作 DOM。


http://www.kler.cn/a/565683.html

相关文章:

  • 【云原生之kubernetes实战】在k8s环境中高效部署Vikunja任务管理工具(含数据库配置)
  • 【Mybatis】如何简单使用mybatis-plus,以及MybatisGenerator自动生成或者实现SQL语句
  • 嵌入式迷雾:现状谜团待解,未来行情走向何方?
  • 微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
  • 优博讯25届春招内推
  • 武汉大学生命科学学院与谱度众合(武汉)生命科技有限公司举行校企联培座谈会
  • MQTT应用环路验证
  • Godot4.3 显示像素风格图片模糊如何设置?
  • Debian安装C语言环境
  • 自主可控:国产CAE一体化平台如何筑基新能源车未来
  • leetcode 75.颜色分类(详解)数组分块c++
  • 【Spring】AOP
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_t
  • [深度学习] 大模型学习2-提示词工程指北
  • 【落羽的落羽 C++】C++入门基础·其之一
  • 芯麦GC1277:电脑散热风扇驱动芯片的优质之选 并可替代传统的0CH477/灿瑞芯片。
  • API,URL,Token,XML,JSON是干嘛的
  • 某镇江 app 练手
  • linux之crosstool-NG(1)生成toolchain
  • TCP/IP 5层协议簇:数据链路层(交换机工作原理)