computed
# 概述
# 源码解析
function computed(getterOrOptions, debugOptions, isSSR = false) {
let getter;
let setter;
if (shared.isFunction(getterOrOptions)) {
getter = getterOrOptions;
} else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
const cRef = new ComputedRefImpl(getter, setter, isSSR);
return cRef;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
class ComputedRefImpl {
constructor(fn, setter, isSSR) {
this.fn = getter;
this.setter = setter;
this["_value"] = undefined;
this.dep = new Dep(this);
this["__v_isRef"] = true;
this["__v_isReadonly"] = undefined;
this.deps = undefined;
this.depsTail = undefined;
this.flags = 16;
this.globalVersion = globalVersion - 1;
this.isSSR = undefined;
this.next = undefined;
this.effect = this;
this.onTrack = undefined;
this.onTrigger = undefined;
this["_warnRecursive"] = undefined;
this["__V_isReadonly"] = !setter;
this.isSSR = isSSR;
}
notify() {
this.flag |= 16;
if (!(this.flags & 8) && activeSub !== this) {
batch(this, true);
return true;
}
}
get value() {
const link = this.dep.track({
target: this,
type: "get",
key: "value"
})
refreshComputed(this);
if (link) {
link.version = this.dep.version;
}
return this._value;
}
set value(newValue) {
if (this.setter) {
this.setter(newValue)
} else {
warn("Write operation failed: computed value is readonly");
}
}
}
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
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
function refreshComputed(computed) {
if (computed.flags & 4 && !(computed.flags & 16)) {
return;
}
computed.flags & =-17;
if (computed.globalVersion === globalVersion) {
return;
}
computed.globalVersion = globalVersion;
if (!computed.isSSR && computed.flags & 128 && (!computed.deps && !computed._dirty || !isDirty(computed))) {
return;
}
computed.flags |= 2;
const dep = computed.dep;
const prevSub = activeSub;
const prevShouldTrack = shouldTrack;
activeSub = computed;
shouldTrack = true;
try {
prepareDeps(computed);
const value = computed.fn(computed._value);
if (dep.version === 0 || hasChanged(value, computed._value)) {
computed.flags |= 128;
computed._value = value;
dep.version++;
}
} catch (err) {
dep.version++;
throw err;
} finally {
activeSub = prevSub;
shouldTrack = prevShouldTrack;
cleanupDep(computed);
computed.flags &= -3;
}
}
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
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
编辑 (opens new window)
上次更新: 2025/08/26, 10:34:53