This article is mainly for the preparation of vuE-next source code, but do not know how to start friends

  1. How to debug Vue3 test case via chrome + vscode
  2. Reactivity Lite (contains only the most basic data flow logic)
  3. Uncopied source code, focusing only on how to implement dataFlow

Through Chrome + VScode debug Vue3 source code

“Blog” : shancw96. Making. IO/blogs / 2020 /…

Open chrome debug screen chrome://inspect

  1. Open Chrome and type the address: chrome://inspect
  2. Select Open Dedicated DevTools for Node

Add the following command to package. json-script

."scripts": {..."test:debug": "node --inspect node_modules/.bin/jest --runInBand"},...Copy the code

Start debugging the test case

npm run test:debug <path_to_test>

Example: Debug reactivity reactivity.spec. ts

Relative path (vue-next root directory) :./packages/reactivity/__tests__/ react.spec.ts

  1. Enable the Chrome ://inspect setting

  2. Add the Debugger to the test file or source file (standalone module)

Added in the test moduleOr standalone module Effect3. Run the debug command to debug a test file

`npm run test:debug ./packages/reactivity/__tests__/reactive.spec.ts`
Copy the code
  1. Automatic debug

Vue3 responsive flow

  1. The object to be responded is passed to the Reactive function for proxy proxy, such as GET and SET

  2. The corresponding callback method is passed to effect function, which will be executed once during initialization to trigger get operation and track operation of proxy and collect current dependencies

  3. Set operation on responsive data triggers trigger operation to execute the corresponding effect list

Data structure:

Code implementation

Reactive function

Reactive: Proxies are used to proxy incoming objects

function reactive(target) {
  // 1. Determine whether it is an object. Proxy can only be an object
  if(! isObject(target))return target;
  const proxy = new Proxy(target, {
    get,
    set,
  });
  return proxy;
}
Copy the code

Get operation: mainly collects dependencies and triggers the track function

let targetMap = new WeakMap(a);function get(target, key, receiver) {
  const res = Reflect.get(target, key, receiver);
  // Rely on collection
  track(target, key);
  // Proxy only proxies the key of the current layer. If the value corresponding to the key is nested, dependency collection needs to be performed
  if (isObject(res)) {
    reactive(res);
  }
  return res;
}
function track(object, key) {
  // If there is no d side effect function, no dependency collection is done
  if(! activeEffect) {return;
  }
  // There are side functions that need to be associated with the specific key of the current object
  // 1. Initialize groups by object
  let depsMap = targetMap.get(object);
  if(! depsMap) { targetMap.set(object, (depsMap =new Map()));
  }
  let dep = depsMap.get(key);
  if(! dep) { depsMap.set(key, (dep =new Set()));
  }
  //2. key <-> Array<Effect>
  if (!dep.has(activeEffect)) {
    dep.add(activeEffect);
    activeEffect.deps.push(dep);
  }
}
Copy the code

Set operation: triggers the list of side effects functions

function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  trigger(target, key);
  return result;
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if(! depsMap.get(key)) {// Never track
    return;
  }
  const effects = new Set(a);// Add all non-activeeffects to the queue
  const add = (effectsToAdd) = > {
    if(! effectsToAdd)return;
    effectsToAdd.forEach((effect) = > {
      if(effect ! == activeEffect) {// question why activeeffect. ans: refer to example 1, if activeEffect is not excluded, trigger will be executed in a loopeffects.add(effect); }}); };// Make a copy of the effect corresponding to the depsMap key and place it in the queue
  if(key ! = =void 0) {
    add(depsMap.get(key));
  }
  // Execute queue
  effects.forEach((effect) = > effect());
}
Copy the code

Effect the function

Effect is a side effect function. It is the same function as Vue2’s Watcher and is executed after the bi-directional binding is triggered

activeEffect = undefined;
function effect(fn) {
  const effect = createReactiveEffect(fn);
  effect();
  return effect;
  function createReactiveEffect(fn) {
    const effect = function reactiveEffect() {
      try {
        activeEffect = effect;
        return fn();
      } finally {
        activeEffect = undefined; }}; effect.deps = [];returneffect; }}Copy the code

Full code :✈️ portal

Write at the end: the above code was heavily cut from the vue3 source code, keeping the most basic logic functions (dependent on collection), there will be many problems, only basic types of testing, don’t mess up.