preface

Recently, when looking at vue3 source code, I came across two concepts that depend on collecting and distributing updates. First, the top two global variables are used to store and locate tracking dependencies, and the warehouse used by track and trigger

let targetMap = new WeakMap();
let activeEffect;
Copy the code

Depend on the collection

role

track(obj, 'get', 'x');
Copy the code

Track will find out if obj.x is tracked. If not, put obj.x in targetMap, use obj.x as the key of the map, and activeEffect as the value of the map.

Aside from value exception handling and the like, track does one thing: plug activeEffect into targetMap;

From this, we can see the format of targetMap as follows

targetMap -> WeakMap()

The name of the key value
targetMap The attribute name Map()
Map The attribute name Set()

Track the source code

Function track(target, key) {let depsMap = targetmap.get (target); if (! DepsMap) {// Add a targetmap. set(target, (depsMap = new Map())); } let dep = depmap.get (key); if (! Dep) {// Add depmap.set (key, (dep = new set())); } // If activeEffect is not added then add an if (! dep.has(activeEffect)) { dep.add(activeEffect); activeEffect.deps.push(dep); if (activeEffect.options.onTrack) { activeEffect.options.onTrack({ effect: activeEffect, target, type, key }); }}}Copy the code

Distributed update

role

Then you write a trigger. Remember how trigger is called in Vue?

trigger(obj, 'set', 'x')
Copy the code

Trigger will only go to targetMap to find the obj.x tracking task, and if it finds one, it will undo it and execute the task.

That is: regardless of the value exception, trigger does only one thing: value from targetMap and then call the function value.

The source code at this point will add the corresponding method to the reactive data according to the type traversal

The source code

Function trigger(target, key) {const depsMap = targetmap. get(target); // Do nothing until you find it. depsMap) return; Const effects = new Set() depmap.get (key).foreach (e => effects.add(e))}Copy the code