@feng3d/reactivity 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/RobotoMono-Medium-DVgDz_OO.woff2 +0 -0
- package/dist/assets/RobotoMono-Regular-BPoF81uy.woff2 +0 -0
- package/dist/assets/index-a2qCSG5V.css +629 -0
- package/dist/assets/index.html-Dyp3udP2.js +200 -0
- package/dist/assets/modulepreload-polyfill-DaKOjhqt.js +37 -0
- package/dist/assets/package-9zMEdmDL.js +2540 -0
- package/dist/assets/src//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274/index.html-a69uOZEV.js +59 -0
- package/dist/assets/src//346/225/260/347/273/204/index.html-CaZ_5kCZ.js +43 -0
- package/dist/docs/.nojekyll +1 -0
- package/dist/docs/assets/hierarchy.js +1 -0
- package/dist/docs/assets/highlight.css +92 -0
- package/dist/docs/assets/icons.js +18 -0
- package/dist/docs/assets/icons.svg +1 -0
- package/dist/docs/assets/main.js +60 -0
- package/dist/docs/assets/navigation.js +1 -0
- package/dist/docs/assets/search.js +1 -0
- package/dist/docs/assets/style.css +1640 -0
- package/dist/docs/classes/ComputedReactivity.html +72 -0
- package/dist/docs/classes/EffectReactivity.html +62 -0
- package/dist/docs/classes/EffectScope.html +40 -0
- package/dist/docs/classes/Reactivity.html +35 -0
- package/dist/docs/classes/RefReactivity.html +57 -0
- package/dist/docs/functions/batchRun.html +15 -0
- package/dist/docs/functions/computed.html +5 -0
- package/dist/docs/functions/effect.html +11 -0
- package/dist/docs/functions/effectScope.html +5 -0
- package/dist/docs/functions/forceTrack.html +6 -0
- package/dist/docs/functions/getCurrentScope.html +4 -0
- package/dist/docs/functions/isProxy.html +5 -0
- package/dist/docs/functions/isReactive.html +5 -0
- package/dist/docs/functions/isRef.html +5 -0
- package/dist/docs/functions/noTrack.html +6 -0
- package/dist/docs/functions/onScopeDispose.html +6 -0
- package/dist/docs/functions/reactive.html +19 -0
- package/dist/docs/functions/ref.html +13 -0
- package/dist/docs/functions/toRaw.html +4 -0
- package/dist/docs/hierarchy.html +1 -0
- package/dist/docs/index.html +129 -0
- package/dist/docs/interfaces/Computed.html +9 -0
- package/dist/docs/interfaces/Effect.html +8 -0
- package/dist/docs/interfaces/Ref.html +9 -0
- package/dist/docs/modules.html +1 -0
- package/dist/docs/types/Reactive.html +3 -0
- package/dist/docs/types/UnReadonly.html +3 -0
- package/dist/files/RobotoMono-Medium.woff2 +0 -0
- package/dist/files/RobotoMono-Regular.woff2 +0 -0
- package/dist/files/ic_code_black_24dp.svg +4 -0
- package/dist/files/ic_search_black_24dp.svg +4 -0
- package/dist/files/main.css +629 -0
- package/dist/files/thumbnails.svg +7 -0
- package/dist/files.json +7 -0
- package/dist/index.html +84 -0
- package/dist/index.js +735 -156
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +735 -156
- package/dist/index.umd.cjs.map +1 -1
- package/dist/screenshots//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274.jpg +0 -0
- package/dist/screenshots//346/225/260/347/273/204.jpg +0 -0
- package/dist/src//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274/index.html +70 -0
- package/dist/src//346/225/260/347/273/204/index.html +65 -0
- package/dist/tags.json +2 -0
- package/lib/Reactivity.d.ts +47 -13
- package/lib/Reactivity.d.ts.map +1 -1
- package/lib/arrayInstrumentations.d.ts +10 -0
- package/lib/arrayInstrumentations.d.ts.map +1 -1
- package/lib/baseHandlers.d.ts +3 -1
- package/lib/baseHandlers.d.ts.map +1 -1
- package/lib/batch.d.ts +17 -5
- package/lib/batch.d.ts.map +1 -1
- package/lib/collectionHandlers.d.ts +21 -0
- package/lib/collectionHandlers.d.ts.map +1 -1
- package/lib/computed.d.ts +75 -27
- package/lib/computed.d.ts.map +1 -1
- package/lib/effect.d.ts +25 -0
- package/lib/effect.d.ts.map +1 -1
- package/lib/effectScope.d.ts +129 -0
- package/lib/effectScope.d.ts.map +1 -0
- package/lib/index.d.ts +6 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/property.d.ts.map +1 -1
- package/lib/reactive.d.ts +58 -17
- package/lib/reactive.d.ts.map +1 -1
- package/lib/ref.d.ts +66 -4
- package/lib/ref.d.ts.map +1 -1
- package/lib/shared/constants.d.ts +7 -7
- package/lib/shared/constants.d.ts.map +1 -1
- package/lib/shared/general.d.ts +1 -1
- package/lib/shared/general.d.ts.map +1 -1
- package/package.json +21 -16
- package/src/Reactivity.ts +57 -15
- package/src/arrayInstrumentations.ts +406 -53
- package/src/baseHandlers.ts +124 -32
- package/src/batch.ts +38 -11
- package/src/collectionHandlers.ts +207 -19
- package/src/computed.ts +92 -43
- package/src/effect.ts +38 -0
- package/src/effectScope.ts +294 -0
- package/src/index.ts +6 -5
- package/src/property.ts +6 -0
- package/src/reactive.ts +67 -20
- package/src/ref.ts +66 -4
package/src/computed.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { Reactivity, forceTrack } from './Reactivity';
|
|
|
4
4
|
/**
|
|
5
5
|
* 创建计算反应式对象。
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* 计算属性会缓存计算结果,只有当依赖发生变化时才会重新计算。
|
|
8
8
|
*
|
|
9
|
-
* @param func
|
|
10
|
-
* @returns 包含 value
|
|
9
|
+
* @param func 计算函数,可以访问其他响应式数据,并返回计算结果
|
|
10
|
+
* @returns 包含 value 属性的计算属性对象
|
|
11
11
|
*/
|
|
12
12
|
export function computed<T>(func: (oldValue?: T) => T): Computed<T>
|
|
13
13
|
{
|
|
@@ -15,7 +15,11 @@ export function computed<T>(func: (oldValue?: T) => T): Computed<T>
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* 计算属性接口。
|
|
19
|
+
*
|
|
20
|
+
* 定义了计算属性的基本结构:
|
|
21
|
+
* 1. value: 计算属性的当前值
|
|
22
|
+
* 2. ComputedSymbol: 用于标识这是一个计算属性
|
|
19
23
|
*/
|
|
20
24
|
export interface Computed<T = any>
|
|
21
25
|
{
|
|
@@ -24,38 +28,56 @@ export interface Computed<T = any>
|
|
|
24
28
|
}
|
|
25
29
|
declare const ComputedSymbol: unique symbol;
|
|
26
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 计算反应式节点接口。
|
|
33
|
+
*
|
|
34
|
+
* 继承自 Computed 接口,表示这是一个计算反应式节点。
|
|
35
|
+
*/
|
|
27
36
|
export interface ComputedReactivity<T = any> extends Computed<T> { }
|
|
28
37
|
|
|
29
38
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* 当使用 computed 函数时,会创建一个 ComputedDep 对象。
|
|
39
|
+
* 计算反应式节点类。
|
|
33
40
|
*
|
|
34
|
-
*
|
|
41
|
+
* 当使用 computed 函数时,会创建一个 ComputedReactivity 对象。
|
|
42
|
+
* 实现了计算属性的核心功能:
|
|
43
|
+
* 1. 缓存计算结果
|
|
44
|
+
* 2. 按需重新计算
|
|
45
|
+
* 3. 依赖追踪
|
|
46
|
+
* 4. 变更通知
|
|
35
47
|
*/
|
|
36
48
|
export class ComputedReactivity<T = any> extends Reactivity<T>
|
|
37
49
|
{
|
|
38
50
|
/**
|
|
51
|
+
* 标识这是一个 ref 对象。
|
|
52
|
+
*
|
|
39
53
|
* @internal
|
|
40
54
|
*/
|
|
41
55
|
readonly __v_isRef = true;
|
|
42
56
|
|
|
43
57
|
/**
|
|
44
|
-
*
|
|
58
|
+
* 计算函数。
|
|
59
|
+
*
|
|
60
|
+
* 用于计算属性值的函数,可以访问其他响应式数据。
|
|
61
|
+
* 当依赖发生变化时,会重新执行此函数。
|
|
45
62
|
*/
|
|
46
63
|
protected _func: (oldValue?: T) => T;
|
|
47
64
|
|
|
48
65
|
/**
|
|
49
|
-
*
|
|
66
|
+
* 失效子节点集合。
|
|
67
|
+
*
|
|
68
|
+
* 记录所有依赖此计算属性的子节点。
|
|
69
|
+
* 当计算属性重新计算时,会通知这些子节点。
|
|
50
70
|
*
|
|
51
71
|
* @private
|
|
52
72
|
*/
|
|
53
73
|
_children = new Map<Reactivity, any>();
|
|
54
74
|
|
|
55
75
|
/**
|
|
56
|
-
*
|
|
76
|
+
* 脏标记。
|
|
57
77
|
*
|
|
58
|
-
*
|
|
78
|
+
* 表示计算属性是否需要重新计算。
|
|
79
|
+
* 当依赖发生变化时,会设置此标记。
|
|
80
|
+
* 重新计算后会清除此标记。
|
|
59
81
|
*
|
|
60
82
|
* @private
|
|
61
83
|
*/
|
|
@@ -64,31 +86,34 @@ export class ComputedReactivity<T = any> extends Reactivity<T>
|
|
|
64
86
|
/**
|
|
65
87
|
* 版本号。
|
|
66
88
|
*
|
|
67
|
-
*
|
|
89
|
+
* 每次重新计算后自动递增。
|
|
90
|
+
* 用于判断子节点中的父节点引用是否过期。
|
|
91
|
+
* 当子节点发现父节点的版本号不匹配时,会重新建立依赖关系。
|
|
68
92
|
*
|
|
69
93
|
* @private
|
|
70
94
|
*/
|
|
71
95
|
_version = -1;
|
|
72
96
|
|
|
73
97
|
/**
|
|
74
|
-
*
|
|
98
|
+
* 获取计算属性的值。
|
|
75
99
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
100
|
+
* 取值时会:
|
|
101
|
+
* 1. 检查是否需要重新计算
|
|
102
|
+
* 2. 建立与父节点的依赖关系
|
|
103
|
+
* 3. 返回当前值
|
|
79
104
|
*/
|
|
80
105
|
get value(): T
|
|
81
106
|
{
|
|
82
107
|
this.runIfDirty();
|
|
83
|
-
|
|
84
108
|
this.track();
|
|
85
109
|
|
|
86
110
|
return this._value;
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
114
|
+
* 创建计算反应式节点。
|
|
115
|
+
*
|
|
116
|
+
* @param func 计算函数,可以访问其他响应式数据,并返回计算结果
|
|
92
117
|
*/
|
|
93
118
|
constructor(func: (oldValue?: T) => T)
|
|
94
119
|
{
|
|
@@ -97,15 +122,15 @@ export class ComputedReactivity<T = any> extends Reactivity<T>
|
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* 冒泡到所有父节点,设置失效子节点字典。
|
|
125
|
+
* 触发更新。
|
|
103
126
|
*
|
|
104
|
-
*
|
|
127
|
+
* 当依赖发生变化时,会调用此方法。
|
|
128
|
+
* 如果当前正在执行计算,会将更新延迟到计算完成后。
|
|
129
|
+
* 否则,立即通知所有父节点进行更新。
|
|
105
130
|
*/
|
|
106
131
|
trigger(): void
|
|
107
132
|
{
|
|
108
|
-
//
|
|
133
|
+
// 正在运行时被触发,需要在运行结束后修复父子节点关系
|
|
109
134
|
if (Reactivity.activeReactivity === this)
|
|
110
135
|
{
|
|
111
136
|
batch(this, Reactivity.activeReactivity === this);
|
|
@@ -115,75 +140,99 @@ export class ComputedReactivity<T = any> extends Reactivity<T>
|
|
|
115
140
|
}
|
|
116
141
|
|
|
117
142
|
/**
|
|
118
|
-
*
|
|
143
|
+
* 执行计算。
|
|
144
|
+
*
|
|
145
|
+
* 执行计算函数,更新当前值。
|
|
146
|
+
* 在计算过程中会:
|
|
147
|
+
* 1. 强制启用依赖跟踪
|
|
148
|
+
* 2. 保存并设置当前活动节点
|
|
149
|
+
* 3. 执行计算函数
|
|
150
|
+
* 4. 恢复活动节点
|
|
119
151
|
*/
|
|
120
152
|
run()
|
|
121
153
|
{
|
|
122
|
-
// 不受嵌套的 effect
|
|
154
|
+
// 不受嵌套的 effect 影响
|
|
123
155
|
forceTrack(() =>
|
|
124
156
|
{
|
|
125
|
-
//
|
|
157
|
+
// 保存当前节点作为父节点
|
|
126
158
|
const parentReactiveNode = Reactivity.activeReactivity;
|
|
127
|
-
|
|
159
|
+
|
|
160
|
+
// 设置当前节点为活跃节点
|
|
128
161
|
Reactivity.activeReactivity = this as any;
|
|
129
162
|
|
|
130
163
|
this._version++;
|
|
131
164
|
this._value = this._func(this._value);
|
|
132
165
|
|
|
133
|
-
//
|
|
166
|
+
// 执行完毕后恢复父节点
|
|
134
167
|
Reactivity.activeReactivity = parentReactiveNode;
|
|
135
168
|
});
|
|
136
169
|
}
|
|
137
170
|
|
|
138
171
|
/**
|
|
139
|
-
*
|
|
172
|
+
* 检查并执行计算。
|
|
173
|
+
*
|
|
174
|
+
* 检查当前节点是否需要重新计算:
|
|
175
|
+
* 1. 如果脏标记为 true,需要重新计算
|
|
176
|
+
* 2. 如果子节点发生变化,需要重新计算
|
|
140
177
|
*
|
|
141
|
-
*
|
|
178
|
+
* 重新计算后会清除脏标记。
|
|
142
179
|
*/
|
|
143
180
|
runIfDirty()
|
|
144
181
|
{
|
|
145
|
-
//
|
|
182
|
+
// 检查是否存在失效子节点字典
|
|
146
183
|
this._isDirty = this._isDirty || this.isChildrenChanged();
|
|
147
184
|
|
|
148
|
-
//
|
|
185
|
+
// 标记为脏的情况下,执行计算
|
|
149
186
|
if (this._isDirty)
|
|
150
187
|
{
|
|
151
|
-
//
|
|
188
|
+
// 立即去除脏标记,避免循环多重计算
|
|
152
189
|
this._isDirty = false;
|
|
153
190
|
|
|
154
|
-
//
|
|
191
|
+
// 执行计算
|
|
155
192
|
this.run();
|
|
156
193
|
}
|
|
157
194
|
}
|
|
158
195
|
|
|
159
196
|
/**
|
|
160
|
-
*
|
|
197
|
+
* 检查子节点是否发生变化。
|
|
198
|
+
*
|
|
199
|
+
* 遍历所有子节点,检查它们的值是否发生变化。
|
|
200
|
+
* 如果发生变化,返回 true,否则返回 false。
|
|
201
|
+
*
|
|
202
|
+
* 在检查过程中会:
|
|
203
|
+
* 1. 临时禁用依赖跟踪
|
|
204
|
+
* 2. 检查每个子节点的值
|
|
205
|
+
* 3. 如果子节点没有变化,重新建立依赖关系
|
|
206
|
+
* 4. 清空子节点集合
|
|
207
|
+
*
|
|
208
|
+
* @returns 是否有子节点发生变化
|
|
161
209
|
*/
|
|
162
210
|
protected isChildrenChanged()
|
|
163
211
|
{
|
|
164
212
|
if (this._children.size === 0) return false;
|
|
165
213
|
|
|
166
|
-
//
|
|
214
|
+
// 检查是否存在子节点发生变化
|
|
167
215
|
let isChanged = false;
|
|
168
216
|
|
|
169
|
-
//
|
|
217
|
+
// 避免在检查过程建立依赖关系
|
|
170
218
|
const preReactiveNode = Reactivity.activeReactivity;
|
|
219
|
+
|
|
171
220
|
Reactivity.activeReactivity = null;
|
|
172
221
|
|
|
173
|
-
//
|
|
222
|
+
// 检查子节点是否发生变化
|
|
174
223
|
this._children.forEach((value, node) =>
|
|
175
224
|
{
|
|
176
225
|
if (isChanged) return;
|
|
177
226
|
if (node.value !== value)
|
|
178
227
|
{
|
|
179
|
-
//
|
|
228
|
+
// 子节点变化,需要重新计算
|
|
180
229
|
isChanged = true;
|
|
181
230
|
|
|
182
231
|
return;
|
|
183
232
|
}
|
|
184
233
|
});
|
|
185
234
|
|
|
186
|
-
//
|
|
235
|
+
// 恢复父节点
|
|
187
236
|
Reactivity.activeReactivity = preReactiveNode;
|
|
188
237
|
|
|
189
238
|
if (!isChanged)
|
|
@@ -195,7 +244,7 @@ export class ComputedReactivity<T = any> extends Reactivity<T>
|
|
|
195
244
|
});
|
|
196
245
|
}
|
|
197
246
|
|
|
198
|
-
//
|
|
247
|
+
// 清空子节点
|
|
199
248
|
this._children.clear();
|
|
200
249
|
|
|
201
250
|
return isChanged;
|
package/src/effect.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { batch, batchRun } from './batch';
|
|
2
2
|
import { ComputedReactivity } from './computed';
|
|
3
|
+
import { activeEffectScope } from './effectScope';
|
|
3
4
|
import { Reactivity } from './Reactivity';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -36,14 +37,28 @@ export class EffectReactivity<T = any> extends ComputedReactivity<T> implements
|
|
|
36
37
|
constructor(func: (oldValue?: T) => T)
|
|
37
38
|
{
|
|
38
39
|
super(func);
|
|
40
|
+
if (activeEffectScope && activeEffectScope.active)
|
|
41
|
+
{
|
|
42
|
+
activeEffectScope.effects.push(this);
|
|
43
|
+
}
|
|
39
44
|
this.runIfDirty();
|
|
40
45
|
}
|
|
41
46
|
|
|
47
|
+
/**
|
|
48
|
+
* 暂停效果。
|
|
49
|
+
*
|
|
50
|
+
* 暂停后,当依赖发生变化时不会自动执行。
|
|
51
|
+
*/
|
|
42
52
|
pause()
|
|
43
53
|
{
|
|
44
54
|
this._isEnable = false;
|
|
45
55
|
}
|
|
46
56
|
|
|
57
|
+
/**
|
|
58
|
+
* 恢复效果。
|
|
59
|
+
*
|
|
60
|
+
* 恢复后,当依赖发生变化时会自动执行。
|
|
61
|
+
*/
|
|
47
62
|
resume()
|
|
48
63
|
{
|
|
49
64
|
if (this._isEnable) return;
|
|
@@ -55,6 +70,22 @@ export class EffectReactivity<T = any> extends ComputedReactivity<T> implements
|
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
|
|
73
|
+
/**
|
|
74
|
+
* 停止效果。
|
|
75
|
+
*
|
|
76
|
+
* 停止后,效果将不再响应依赖的变化。
|
|
77
|
+
*/
|
|
78
|
+
stop()
|
|
79
|
+
{
|
|
80
|
+
this._isEnable = false;
|
|
81
|
+
EffectReactivity.pausedQueueEffects.delete(this);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 触发效果执行。
|
|
86
|
+
*
|
|
87
|
+
* 当依赖发生变化时,会调用此方法。
|
|
88
|
+
*/
|
|
58
89
|
trigger()
|
|
59
90
|
{
|
|
60
91
|
batchRun(() =>
|
|
@@ -72,6 +103,7 @@ export class EffectReactivity<T = any> extends ComputedReactivity<T> implements
|
|
|
72
103
|
}
|
|
73
104
|
});
|
|
74
105
|
}
|
|
106
|
+
|
|
75
107
|
private static pausedQueueEffects = new WeakSet<EffectReactivity>();
|
|
76
108
|
|
|
77
109
|
/**
|
|
@@ -101,8 +133,14 @@ export interface Effect
|
|
|
101
133
|
* 暂停。
|
|
102
134
|
*/
|
|
103
135
|
pause: () => void;
|
|
136
|
+
|
|
104
137
|
/**
|
|
105
138
|
* 恢复。
|
|
106
139
|
*/
|
|
107
140
|
resume: () => void;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 停止。
|
|
144
|
+
*/
|
|
145
|
+
stop: () => void;
|
|
108
146
|
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import type { Effect as ReactiveEffect } from './effect';
|
|
2
|
+
import { warn } from './shared/general';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 当前活动的效果作用域
|
|
6
|
+
*/
|
|
7
|
+
export let activeEffectScope: EffectScope | undefined;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 效果作用域类
|
|
11
|
+
*
|
|
12
|
+
* 用于管理一组相关的响应式效果,可以统一控制它们的生命周期。
|
|
13
|
+
*/
|
|
14
|
+
export class EffectScope
|
|
15
|
+
{
|
|
16
|
+
/**
|
|
17
|
+
* 作用域是否处于活动状态
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
private _active = true;
|
|
21
|
+
/**
|
|
22
|
+
* 跟踪 on 方法的调用次数,允许多次调用 on 方法
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
private _on = 0;
|
|
26
|
+
/**
|
|
27
|
+
* 存储当前作用域中的所有效果
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
effects: ReactiveEffect[] = [];
|
|
31
|
+
/**
|
|
32
|
+
* 存储清理函数
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
cleanups: (() => void)[] = [];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 作用域是否被暂停
|
|
39
|
+
*/
|
|
40
|
+
private _isPaused = false;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 父作用域,仅由非分离的作用域分配
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
parent: EffectScope | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* 记录未分离的子作用域
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
scopes: EffectScope[] | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 在父作用域的 scopes 数组中记录子作用域的索引,用于优化移除操作
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
private index: number | undefined;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 构造函数
|
|
60
|
+
* @param detached 是否创建分离的作用域
|
|
61
|
+
*/
|
|
62
|
+
constructor(public detached = false)
|
|
63
|
+
{
|
|
64
|
+
this.parent = activeEffectScope;
|
|
65
|
+
if (!detached && activeEffectScope)
|
|
66
|
+
{
|
|
67
|
+
this.index =
|
|
68
|
+
(activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(
|
|
69
|
+
this,
|
|
70
|
+
) - 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 获取作用域是否处于活动状态
|
|
76
|
+
*/
|
|
77
|
+
get active(): boolean
|
|
78
|
+
{
|
|
79
|
+
return this._active;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 暂停作用域
|
|
84
|
+
*
|
|
85
|
+
* 暂停当前作用域及其所有子作用域和效果
|
|
86
|
+
*/
|
|
87
|
+
pause(): void
|
|
88
|
+
{
|
|
89
|
+
if (this._active)
|
|
90
|
+
{
|
|
91
|
+
this._isPaused = true;
|
|
92
|
+
let i: number, l: number;
|
|
93
|
+
|
|
94
|
+
if (this.scopes)
|
|
95
|
+
{
|
|
96
|
+
for (i = 0, l = this.scopes.length; i < l; i++)
|
|
97
|
+
{
|
|
98
|
+
this.scopes[i].pause();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (i = 0, l = this.effects.length; i < l; i++)
|
|
102
|
+
{
|
|
103
|
+
this.effects[i].pause();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 恢复作用域
|
|
110
|
+
*
|
|
111
|
+
* 恢复当前作用域及其所有子作用域和效果
|
|
112
|
+
*/
|
|
113
|
+
resume(): void
|
|
114
|
+
{
|
|
115
|
+
if (this._active)
|
|
116
|
+
{
|
|
117
|
+
if (this._isPaused)
|
|
118
|
+
{
|
|
119
|
+
this._isPaused = false;
|
|
120
|
+
let i: number, l: number;
|
|
121
|
+
|
|
122
|
+
if (this.scopes)
|
|
123
|
+
{
|
|
124
|
+
for (i = 0, l = this.scopes.length; i < l; i++)
|
|
125
|
+
{
|
|
126
|
+
this.scopes[i].resume();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (i = 0, l = this.effects.length; i < l; i++)
|
|
130
|
+
{
|
|
131
|
+
this.effects[i].resume();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 在作用域中运行函数
|
|
139
|
+
* @param fn 要运行的函数
|
|
140
|
+
* @returns 函数的返回值
|
|
141
|
+
*/
|
|
142
|
+
run<T>(fn: () => T): T | undefined
|
|
143
|
+
{
|
|
144
|
+
if (this._active)
|
|
145
|
+
{
|
|
146
|
+
const currentEffectScope = activeEffectScope;
|
|
147
|
+
|
|
148
|
+
try
|
|
149
|
+
{
|
|
150
|
+
activeEffectScope = this;
|
|
151
|
+
|
|
152
|
+
return fn();
|
|
153
|
+
}
|
|
154
|
+
finally
|
|
155
|
+
{
|
|
156
|
+
activeEffectScope = currentEffectScope;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (__DEV__)
|
|
160
|
+
{
|
|
161
|
+
warn(`cannot run an inactive effect scope.`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 前一个作用域
|
|
167
|
+
*/
|
|
168
|
+
prevScope: EffectScope | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* 激活作用域
|
|
171
|
+
* 仅应在非分离的作用域上调用
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
174
|
+
on(): void
|
|
175
|
+
{
|
|
176
|
+
if (++this._on === 1)
|
|
177
|
+
{
|
|
178
|
+
this.prevScope = activeEffectScope;
|
|
179
|
+
activeEffectScope = this;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 停用作用域
|
|
185
|
+
* 仅应在非分离的作用域上调用
|
|
186
|
+
* @internal
|
|
187
|
+
*/
|
|
188
|
+
off(): void
|
|
189
|
+
{
|
|
190
|
+
if (this._on > 0 && --this._on === 0)
|
|
191
|
+
{
|
|
192
|
+
activeEffectScope = this.prevScope;
|
|
193
|
+
this.prevScope = undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 停止作用域
|
|
199
|
+
*
|
|
200
|
+
* 停止当前作用域及其所有子作用域和效果,并执行清理函数
|
|
201
|
+
* @param fromParent 是否由父作用域调用
|
|
202
|
+
*/
|
|
203
|
+
stop(fromParent?: boolean): void
|
|
204
|
+
{
|
|
205
|
+
if (this._active)
|
|
206
|
+
{
|
|
207
|
+
this._active = false;
|
|
208
|
+
let i: number, l: number;
|
|
209
|
+
|
|
210
|
+
for (i = 0, l = this.effects.length; i < l; i++)
|
|
211
|
+
{
|
|
212
|
+
this.effects[i].stop();
|
|
213
|
+
}
|
|
214
|
+
this.effects.length = 0;
|
|
215
|
+
|
|
216
|
+
for (i = 0, l = this.cleanups.length; i < l; i++)
|
|
217
|
+
{
|
|
218
|
+
this.cleanups[i]();
|
|
219
|
+
}
|
|
220
|
+
this.cleanups.length = 0;
|
|
221
|
+
|
|
222
|
+
if (this.scopes)
|
|
223
|
+
{
|
|
224
|
+
for (i = 0, l = this.scopes.length; i < l; i++)
|
|
225
|
+
{
|
|
226
|
+
this.scopes[i].stop(true);
|
|
227
|
+
}
|
|
228
|
+
this.scopes.length = 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 嵌套作用域,从父作用域中解除引用以避免内存泄漏
|
|
232
|
+
if (!this.detached && this.parent && !fromParent)
|
|
233
|
+
{
|
|
234
|
+
// 优化的 O(1) 移除
|
|
235
|
+
const last = this.parent.scopes!.pop();
|
|
236
|
+
|
|
237
|
+
if (last && last !== this)
|
|
238
|
+
{
|
|
239
|
+
this.parent.scopes![this.index!] = last;
|
|
240
|
+
last.index = this.index!;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
this.parent = undefined;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 创建效果作用域对象
|
|
250
|
+
*
|
|
251
|
+
* 可以捕获在其中创建的响应式效果(即计算属性和观察者),以便这些效果可以一起处理。
|
|
252
|
+
*
|
|
253
|
+
* @param detached 是否创建分离的作用域
|
|
254
|
+
* @see {@link https://vuejs.org/api/reactivity-advanced.html#effectscope}
|
|
255
|
+
*/
|
|
256
|
+
export function effectScope(detached?: boolean): EffectScope
|
|
257
|
+
{
|
|
258
|
+
return new EffectScope(detached);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 获取当前活动的效果作用域
|
|
263
|
+
*
|
|
264
|
+
* @returns 当前活动的效果作用域,如果没有则返回 undefined
|
|
265
|
+
* @see {@link https://vuejs.org/api/reactivity-advanced.html#getcurrentscope}
|
|
266
|
+
*/
|
|
267
|
+
export function getCurrentScope(): EffectScope | undefined
|
|
268
|
+
{
|
|
269
|
+
return activeEffectScope;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* 在当前活动的效果作用域上注册清理回调
|
|
274
|
+
*
|
|
275
|
+
* 当关联的效果作用域停止时,将调用此回调函数。
|
|
276
|
+
*
|
|
277
|
+
* @param fn 要附加到作用域清理的回调函数
|
|
278
|
+
* @param failSilently 是否静默失败
|
|
279
|
+
* @see {@link https://vuejs.org/api/reactivity-advanced.html#onscopedispose}
|
|
280
|
+
*/
|
|
281
|
+
export function onScopeDispose(fn: () => void, failSilently = false): void
|
|
282
|
+
{
|
|
283
|
+
if (activeEffectScope)
|
|
284
|
+
{
|
|
285
|
+
activeEffectScope.cleanups.push(fn);
|
|
286
|
+
}
|
|
287
|
+
else if (__DEV__ && !failSilently)
|
|
288
|
+
{
|
|
289
|
+
warn(
|
|
290
|
+
`onScopeDispose() is called when there is no active effect scope` +
|
|
291
|
+
` to be associated with.`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { batchRun } from './batch';
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export { isProxy, isReactive, reactive, type Reactive } from './reactive';
|
|
6
|
-
export {
|
|
2
|
+
export { computed, type Computed, type ComputedReactivity } from './computed';
|
|
3
|
+
export { effect, EffectReactivity, type Effect } from './effect';
|
|
4
|
+
export { effectScope, EffectScope, getCurrentScope, onScopeDispose } from './effectScope';
|
|
5
|
+
export { isProxy, isReactive, reactive, type Reactive, type UnReadonly } from './reactive';
|
|
6
|
+
export { forceTrack, noTrack, Reactivity } from './Reactivity';
|
|
7
|
+
export { isRef, ref, RefReactivity, type Ref } from './ref';
|
|
7
8
|
export { toRaw } from './shared/general';
|
|
8
9
|
|