ref 实现

第一步

index.ts

1
2
3
4
5
6
export * from './reactive';
export * from './effect';

// -----------------------------新增开始-----------------------------
export * from './ref';
// -----------------------------新增结束-----------------------------

ref.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { toReactive } from './reactive';
import { activeEffect, trackEffect, triggerEffects } from './effect';
import { createDep } from './reactiveEffect';

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

function createRef(value) {
return new RefImpl(value);
}

class RefImpl {
// ref 标识
public __v_isRef = true;
// 保存 ref 值
public _value;
// 收集 effect
public dep;

constructor(public rawValue) {
this._value = toReactive(rawValue);
}

get value() {
trackRefValue(this);
return this._value;
}

set value(newValue) {
if (newValue !== this.rawValue) {
this.rawValue = newValue;
this._value = newValue;
triggerRefValue(this);
}
}
}

function trackRefValue(ref) {
if (activeEffect) {
trackEffect(activeEffect, ref.dep = ref.dep || createDep(() => ref.dep = undefined, 'undefined'));
}
}

function triggerRefValue(ref) {
const dep = ref.dep;
if (dep) {
triggerEffects(dep);
}
}

reactive.ts

1
2
3
4
5
6
import { isObject } from '@vue/shared';

...
export function toReactive(value) {
return isObject(value) ? reactive(value) : value;
}