Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • reactivity响应式

    • ref
    • reactive
    • 基础对象的代理
    • 数组代理的方法
    • 集合对象的代理
    • Reflect和Proxy详解
    • 依赖的收集与触发
    • effectScope解析
    • effect解析
    • reactive响应式依赖的收集与触发监听
      • 概览
      • 源码分析
        • track方法
        • trigger方法
    • 批量更新实现
    • ReactiveEffect类介绍
    • computed
  • 5.18源码学习》
  • reactivity响应式
东流
2025-08-22
目录

reactive响应式依赖的收集与触发监听

# 概览

在BaseReactiveHandler类的get方法中,有如下代码块if (!isReadonly2){track(target, "get", key);},这表示通过reactive、shallowReactive创建的响应式对象,非只读的,当读取代理对象proxyTarget的某个属性key时,都会被该get方法拦截,即调用track()方法建立依赖。

而当对代理对象proxyTarget进行赋值或更新某个属性的值时,会被set方法拦截,即调用trigger()方法触发依赖(而删除会被deleteProperty拦截)。

因此对于reactive响应式对象的响应式处理,和track与trigger方法密不可分。

本文主要介绍track与trigger是如何进行依赖的收集与触发的全流程。

# 源码分析

在vue3中,维护了一个全局的targetMap WeakMap实例对象,用于存储响应式对象与依赖的映射关系。

const targetMap = new WeakMap();
1

# track方法

track方法收集依赖就是往变量targetMap中添加相关元素,存储响应式对象与依赖的映射关系。

track的源码实现如下:

function track(target, type, key) {
    if (shouldTrack && activeSub) {
        let depsMap = targetMap.get(target);
        if (!depsMap) {
            targetMap.set(target, depsMap = new Map());
        }
        let dep = depsMap.get(key);
        if (!dep) {
            depsMap.set(key, dep = new Dep());
            dep.map = depsMap;
            dep.key = key;
        }
        dep.track();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这里暂且不论shouldTrack和activeSub,假定满足track的条件。首先从targetMap中读取depsMap,若depsMap中不存在,则创建一个新的Map的实例,并将其赋值给depsMap,并且存储到targetMap中。然后从depsMap中获取key对应的依赖关系dep,同理,若dep不存在,则创建一个新的Dep实例,并将其赋值给dep,并且存储到depsMap中,然后将dep的map和key分别绑定depsMap、key。最后调用dep.track()方法。

dep.track()执行后,会将当前的activeSub添加到dep的subs数组中?。

# trigger方法

track方法的源码实现如下:

function trigger(target, type, key, newValue, oldValue, oldTarget) {
    const depsMap = targetMap.get(target);
    if (!depsMap) {
        globalVersion++;
        return;
    }
    const run = (dep) => {
        if (dep) {
            dep.trigger();
        }
    };
    startBatch();
    if (type === "clear") {
        depsMap.forEach(run);
    } else {
        const targetIsArray = isArray(target);
        const isArrayIndex = targetIsArray && isIntegerKey(key);
        if (targetIsArray && key === "length") {
            const newLength = Number(newValue);
            depsMap.forEach((dep, key2) => {
                if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) {
                    run(dep);
                }
            });
        } else {
            if (key !== void 0 || depsMap.has(void 0)) {
                run(depsMap.get(key));
            }
            if (isArrayIndex) {
                run(depsMap.get(ARRAY_ITERATE_KEY));
            }
            switch (type) {
                case "add":
                    if (!targetIsArray) {
                        run(depsMap.get(ITERATE_KEY));
                        if (isMap(target)) {
                            run(depsMap.get(MAP_KEY_ITERATE_KEY));
                        }
                    } else if (isArrayIndex) {
                        run(depsMap.get("length"));
                    }
                    break;
                case "delete":
                    if (!targetIsArray) {
                        run(depsMap.get(ITERATE_KEY));
                        if (isMap(target)) {
                            run(depsMap.get(MAP_KEY_ITERATE_KEY));
                        }
                    }
                    break;
                case "set":
                    if (isMap(target)) {
                        run(depsMap.get(ITERATE_KEY));
                    }
                    break;
            }
        }
    }
    endBatch();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
编辑 (opens new window)
上次更新: 2025/08/26, 10:34:53
effect解析
批量更新实现

← effect解析 批量更新实现→

最近更新
01
computed
08-26
02
ReactiveEffect类介绍
08-26
03
批量更新实现
08-25
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式