This article focuses on the reactive principle of VUE.

The preparatory work

In order for typescript to support ES6 syntax, DOM and ES6 need to be introduced.

Open tsconfig.json and add the following configuration items:

{
    "lib": ["DOM"."ES6"]}Copy the code

Writing Reactive code

Create a SRC/reactivity/reactive. Ts file.

import {track, trigger} from './effect'
export function reactive (raw) {
  return new Proxy(raw, {
    get (target, key) {
      const res = Reflect.get(target, key)
      track(target, key)
      return res
    },
    set (target, key, value) {
      const res = Reflect.set(target, key, value)
      trigger(target, key);
      return res
    }
  })
}
Copy the code

Write the test case: SRC/reactivity/tests/reactive spec. Ts.

import {reactive} from '.. /reactive'
describe("reactive".() = > {
  it("happy path".() = > {
    const orgin = {
      foo: 1
    }
    const obversed = reactive(orgin);
    expect(obversed).not.toBe(orgin);
    expect(obversed.foo).toBe(1); })})Copy the code

Writing Effect code

Create the SRC /reactivity/effect.ts file.

class ReactiveEffect {
  private _fn: any
  constructor (_fn) {
    this._fn = _fn
  }
  run () {
    activeEffect = this;
    this._fn()
  }
}
const targetMap = new Map(a)// Collect dependencies
export function track (target, key) {
  // Define dependencies
  // target -> key -> dep
  // const dep = new Set()
  let depsMap = targetMap.get(target);
  // Create a depsMap if you don't have one
  if(! depsMap) { depsMap =new Map()
    targetMap.set(target, depsMap)
  }
  let dep = depsMap.get(key);
  if(! dep) { dep =new Set(a); depsMap.set(key, dep) } dep.add(activeEffect); }export function trigger (target, key) {
  let depsMap = targetMap.get(target)
  let dep = depsMap.get(key)
  for (const effect of dep) {
    effect.run()
  }
}

let activeEffect;

export function effect (fn) {
  const _effect = new ReactiveEffect(fn)
  _effect.run()
}
Copy the code

Write the test case: the SRC/reactivity/tests/effect. The spec. Ts.

import {reactive} from '.. /reactive'
import {effect} from '.. /effect'
describe('effect'.() = > {
  it.skip('happy path'.() = > {
    const user = reactive({
      age: 10
    })
    let newAge;
    effect(() = > {
      newAge = user.age + 1;
    })
    expect(newAge).toBe(11);
    user.age ++;
    expect(newAge).toBe(12); })})Copy the code