Skip to content

Commit

Permalink
feat: ref should be reactive
Browse files Browse the repository at this point in the history
  • Loading branch information
JeasonSun committed Mar 22, 2022
1 parent 100f724 commit 593b00e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 28 deletions.
28 changes: 24 additions & 4 deletions src/reactivity/__tests__/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import { ref } from "../src";
import { effect, ref } from "../src";

describe("reactive/ref", () => {
it('should hold a value', () => {
it("should hold a value", () => {
const a = ref(1);
expect(a.value).toBe(1);
a.value = 2;
expect(a.value).toBe(2);
})
})
});

it("should be reactive", () => {
const a = ref(1);
let dummy;
let calls = 0;
effect(() => {
calls++;
dummy = a.value;
});
expect(calls).toBe(1);
expect(dummy).toBe(1);

a.value = 2;
expect(calls).toBe(2);
expect(dummy).toBe(2);

// // 如果设置相同的值,不需要trigger effect
a.value = 2;
expect(calls).toBe(2);
});
});
54 changes: 30 additions & 24 deletions src/reactivity/src/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ let shouldTrack = false;
export class ReactiveEffect {
deps: any[] = [];
active = true;
constructor(public fn, public scheduler?) {

}
constructor(public fn, public scheduler?) {}

run() {

if (!this.active) {
return this.fn();
}
Expand All @@ -30,20 +27,19 @@ export class ReactiveEffect {

stop() {
if (this.active) {
this.deps.forEach(dep => {
dep.delete(this)
})
this.deps.forEach((dep) => {
dep.delete(this);
});
this.deps.length = 0;
this.active = false;
}

}
}

export function effect(fn, options?) {
const _effect = new ReactiveEffect(fn);
if (options) {
extend(_effect, options)
extend(_effect, options);
}
_effect.run();

Expand All @@ -60,12 +56,11 @@ export function stop(runner) {

export function track(target, key) {
// 如果响应式数据不在effect中,那直接不用收集了,因为收集了也没有触发更新的时机。
if (!activeEffect) {
return;
}
if (!shouldTrack) {

if (!isTracking()) {
return;
}

let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
Expand All @@ -77,25 +72,36 @@ export function track(target, key) {
dep = new Set();
depsMap.set(key, dep);
}
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
(activeEffect as any).deps.push(dep);
}

trackEffect(dep);
}

export function trigger(target, key) {
const depsMap = targetMap.get(target);
if(!depsMap){
if (!depsMap) {
// 没有被track, 比如 shallowReactive.spec.ts中,shallowReactive,没有收集依赖,但是在修改props.n时候触发更新,找不到depsMap
return;
}
const deps = depsMap.get(key);
deps.forEach(effect => {
triggerEffect(deps);
}

export function isTracking() {
return shouldTrack && activeEffect !== undefined;
}

export function trackEffect(dep) {
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
(activeEffect as any).deps.push(dep);
}
}

export function triggerEffect(deps) {
deps.forEach((effect) => {
if (effect.scheduler) {
effect.scheduler()
effect.scheduler();
} else {
effect.run()
effect.run();
}
})
}
});
}
8 changes: 8 additions & 0 deletions src/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { hasChanged } from "../../shared/src";
import { isTracking, trackEffect, triggerEffect } from "./effect";

export class RefImpl {
private _rawValue: any;
private _value: any;
public dep: Set<unknown>; // TODO:定义一下type Dep

constructor(value) {
this._rawValue = value;
this._value = value;
this.dep = new Set();
}

get value() {
if (isTracking()) {
trackEffect(this.dep);
}
return this._value;
}

set value(newValue) {
if (hasChanged(this._rawValue, newValue)) {
this._rawValue = newValue;
this._value = newValue;
triggerEffect(this.dep);
}
}
}
Expand Down

0 comments on commit 593b00e

Please sign in to comment.