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