目录

vue2 中,为什么要 Dep.target 来收集依赖

在 Vue 2 中,Dep.target 主要用于收集依赖和触发依赖更新。Vue 的响应式系统使用了基于观察者模式的设计,其中有三个核心概念:ObserverDep(Dependency)和 Watcher

  1. Observer(观察者):负责将对象转化为响应式对象,即监听对象属性的变化。

  2. Dep(Dependency) :用于收集依赖,每个响应式对象上都有一个对应的 Dep 对象,其中存储了所有依赖于该对象的 Watcher

  3. Watcher(观察者) :负责创建视图和更新视图的逻辑,当依赖的数据发生变化时,Watcher 负责触发更新。

Dep.target 在这个机制中充当全局唯一的标志,用来指示当前正在进行依赖收集的 Watcher。在 Watcher 初始化过程中,会将 Dep.target 设置为当前 Watcher,然后触发数据的读取操作。当读取数据时,Observer 会检测当前是否有正在进行依赖收集的 Watcher(即 Dep.target 是否存在),如果有,就将该 Watcher 添加到当前属性对应的 Dep 中。

为什么要这样设计呢?

  • 精确定位依赖关系 :通过 Dep.target 的设置,可以精确地知道是哪个 Watcher 正在进行依赖收集。这样,每个属性的依赖关系都可以被精确地管理,避免不必要的更新。

  • 自动依赖收集:由于 JavaScript 是单线程的,通过在读取数据时收集依赖,可以自动追踪数据的变化,从而触发视图的更新。这样,开发者无需手动管理依赖关系,系统可以自动进行依赖追踪。

示例代码可能如下所示:

javascript 复制代码
// Dep 类用于收集依赖
class Dep {
  constructor() {
    this.subscribers = [];
  }

  // 添加依赖
  depend() {
    if (Dep.target && !this.subscribers.includes(Dep.target)) {
      this.subscribers.push(Dep.target);
    }
  }

  // 通知依赖更新
  notify() {
    this.subscribers.forEach(sub => sub.update());
  }
}

// Dep.target 用于指示当前的 Watcher
Dep.target = null;

// Watcher 类负责创建视图和更新视图的逻辑
class Watcher {
  constructor() {
    // 设置 Dep.target 为当前 Watcher
    Dep.target = this;
    // 在读取数据时,会触发依赖收集
    this.value = data.someProperty; 
    // 重置 Dep.target
    Dep.target = null;
  }

  // 更新视图的逻辑
  update() {
    // 实现更新的逻辑
  }
}

// Observer 类负责将对象转化为响应式对象
class Observer {
  constructor(data) {
    this.data = data;
    this.observe(data);
  }

  observe(data) {
    Object.keys(data).forEach(key => {
      let dep = new Dep();
      let val = data[key];

      Object.defineProperty(data, key, {
        get() {
          dep.depend(); // 在读取数据时收集依赖
          return val;
        },
        set(newVal) {
          if (val !== newVal) {
            val = newVal;
            dep.notify(); // 在数据变化时通知依赖更新
          }
        }
      });
    });
  }
}

// 示例数据
const data = {
  someProperty: 42
};

// 创建 Observer 实例,实现响应式
const observer = new Observer(data);

// 创建 Watcher 实例,用于更新视图
const watcher = new Watcher();

在这个简化的示例中,Dep.target 的设置和重置使得在读取数据时能够正确地收集依赖。这种机制使得 Vue 能够实现高效的响应式更新。

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
胚芽鞘6817 小时前
vue + element-plus自定义表单验证(修改密码业务)
javascript·vue.js·elementui
诸葛亮的芭蕉扇8 小时前
D3路网图技术文档
前端·javascript·vue.js·microsoft
萌萌哒草头将军9 小时前
😡😡😡早知道有这两个 VueRouter 增强插件,我还加什么班!🚀🚀🚀
前端·vue.js·vue-router
苏卫苏卫苏卫10 小时前
【Vue】案例——To do list:
开发语言·前端·javascript·vue.js·笔记·list
聪明的墨菲特i11 小时前
React与Vue:哪个框架更适合入门?
开发语言·前端·javascript·vue.js·react.js
Nuyoah.11 小时前
《Vue3学习手记2》
javascript·vue.js·学习
小万编程13 小时前
基于SpringBoot+Vue的汽车展销平台【提供源码+论文1.5W字+答辩PPT+项目部署】
vue.js·spring boot·汽车
前端九哥13 小时前
🌟Vue 3 全局注册组件全攻略(三种常用方式讲透透!)!🌟
前端·vue.js
翠莲13 小时前
vue中使用swiper坑记录
前端·javascript·vue.js
前端九哥13 小时前
🎯Vue 3 少量全局数据共享的最佳实践(无需 Vuex/Pinia)
前端·vue.js