Skip to content

Commit

Permalink
feat: ref
Browse files Browse the repository at this point in the history
cuixiaorui committed Aug 17, 2021
1 parent 348f97b commit f26ff79
Showing 4 changed files with 100 additions and 3 deletions.
35 changes: 35 additions & 0 deletions src/reactivity/__tests__/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { effect } from "../src/effect";
import { ref } from "../src/ref";
describe("ref", () => {
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);
// same value should not trigger
a.value = 2;
expect(calls).toBe(2);
expect(dummy).toBe(2);
});

it("should make nested properties reactive", () => {
const a = ref({
count: 1,
});
let dummy;
effect(() => {
dummy = a.value.count;
});
expect(dummy).toBe(1);
a.value.count = 2;
expect(dummy).toBe(2);
});
});
4 changes: 2 additions & 2 deletions src/reactivity/src/effect.ts
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ export function track(target, type, key) {
trackEffects(dep);
}

function trackEffects(dep) {
export function trackEffects(dep) {
// 用 dep 来存放所有的 effect
dep.add(activeEffect);
(activeEffect as any).deps.push(dep);
@@ -108,7 +108,7 @@ export function trigger(target, type, key) {
triggerEffects(createDep(effects));
}

function triggerEffects(dep) {
export function triggerEffects(dep) {
// 执行收集到的所有的 effect 的 run 方法
for (const effect of dep) {
if (effect.scheduler) {
58 changes: 58 additions & 0 deletions src/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { trackEffects, triggerEffects } from "./effect";
import { createDep } from "./dep";
import { isObject, hasChanged } from "../../shared";
import { reactive } from "./reactive";

export class RefImpl {
private _rawValue: any;
private _value: any;
public dep;

constructor(value) {
this._rawValue = value;
// 看看value 是不是一个对象,如果是一个对象的话
// 那么需要用 reactive 包裹一下
this._value = convert(value);
this.dep = createDep();
}

get value() {
// 收集依赖
trackRefValue(this);
return this._value;
}

set value(newValue) {
// 当新的值不等于老的值的话,
// 那么才需要触发依赖
if (hasChanged(newValue, this._rawValue)) {
// 更新值
this._value = convert(newValue);
this._rawValue = newValue;
// 触发依赖
triggerRefValue(this);
}
}
}

export function ref(value) {
return createRef(value);
}

function convert(value) {
return isObject(value) ? reactive(value) : value;
}

function createRef(value) {
const refImpl = new RefImpl(value);

return refImpl;
}

function triggerRefValue(ref) {
triggerEffects(ref.dep);
}

function trackRefValue(ref) {
trackEffects(ref.dep);
}
6 changes: 5 additions & 1 deletion src/shared/index.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,11 @@ export const camelize = (str: string): string => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ""));
};

export const extend = Object.assign
export const extend = Object.assign;

export function hasChanged(value, oldValue) {
return !Object.is(value, oldValue);
}

/**
* @private

0 comments on commit f26ff79

Please sign in to comment.