@feng3d/reactivity 1.0.5 → 1.0.7

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.
Files changed (97) hide show
  1. package/dist/assets/RobotoMono-Medium-DVgDz_OO.woff2 +0 -0
  2. package/dist/assets/RobotoMono-Regular-BPoF81uy.woff2 +0 -0
  3. package/dist/assets/index-a2qCSG5V.css +629 -0
  4. package/dist/assets/index.html-Dyp3udP2.js +200 -0
  5. package/dist/assets/modulepreload-polyfill-DaKOjhqt.js +37 -0
  6. package/dist/assets/package-DuJynByc.js +2539 -0
  7. package/dist/assets/src//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274/index.html-C3hbV3IR.js +59 -0
  8. package/dist/assets/src//346/225/260/347/273/204/index.html-CHK6WEhd.js +43 -0
  9. package/dist/docs/.nojekyll +1 -0
  10. package/dist/docs/assets/hierarchy.js +1 -0
  11. package/dist/docs/assets/highlight.css +92 -0
  12. package/dist/docs/assets/icons.js +18 -0
  13. package/dist/docs/assets/icons.svg +1 -0
  14. package/dist/docs/assets/main.js +60 -0
  15. package/dist/docs/assets/navigation.js +1 -0
  16. package/dist/docs/assets/search.js +1 -0
  17. package/dist/docs/assets/style.css +1640 -0
  18. package/dist/docs/classes/EffectScope.html +40 -0
  19. package/dist/docs/functions/batchRun.html +15 -0
  20. package/dist/docs/functions/computed.html +5 -0
  21. package/dist/docs/functions/effect.html +11 -0
  22. package/dist/docs/functions/effectScope.html +5 -0
  23. package/dist/docs/functions/forceTrack.html +6 -0
  24. package/dist/docs/functions/getCurrentScope.html +4 -0
  25. package/dist/docs/functions/isProxy.html +5 -0
  26. package/dist/docs/functions/isReactive.html +5 -0
  27. package/dist/docs/functions/isRef.html +5 -0
  28. package/dist/docs/functions/noTrack.html +6 -0
  29. package/dist/docs/functions/onScopeDispose.html +6 -0
  30. package/dist/docs/functions/reactive.html +19 -0
  31. package/dist/docs/functions/ref.html +13 -0
  32. package/dist/docs/functions/toRaw.html +4 -0
  33. package/dist/docs/hierarchy.html +1 -0
  34. package/dist/docs/index.html +129 -0
  35. package/dist/docs/interfaces/Computed.html +9 -0
  36. package/dist/docs/interfaces/Effect.html +8 -0
  37. package/dist/docs/interfaces/Ref.html +9 -0
  38. package/dist/docs/modules.html +1 -0
  39. package/dist/docs/types/Reactive.html +3 -0
  40. package/dist/docs/types/UnReadonly.html +3 -0
  41. package/dist/files/RobotoMono-Medium.woff2 +0 -0
  42. package/dist/files/RobotoMono-Regular.woff2 +0 -0
  43. package/dist/files/ic_code_black_24dp.svg +4 -0
  44. package/dist/files/ic_search_black_24dp.svg +4 -0
  45. package/dist/files/main.css +629 -0
  46. package/dist/files/thumbnails.svg +7 -0
  47. package/dist/files.json +7 -0
  48. package/dist/index.html +84 -0
  49. package/dist/index.js +733 -157
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.umd.cjs +733 -157
  52. package/dist/index.umd.cjs.map +1 -1
  53. package/dist/screenshots//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274.jpg +0 -0
  54. package/dist/screenshots//346/225/260/347/273/204.jpg +0 -0
  55. 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
  56. package/dist/src//346/225/260/347/273/204/index.html +65 -0
  57. package/dist/tags.json +2 -0
  58. package/lib/Reactivity.d.ts +47 -13
  59. package/lib/Reactivity.d.ts.map +1 -1
  60. package/lib/arrayInstrumentations.d.ts +10 -0
  61. package/lib/arrayInstrumentations.d.ts.map +1 -1
  62. package/lib/baseHandlers.d.ts +3 -1
  63. package/lib/baseHandlers.d.ts.map +1 -1
  64. package/lib/batch.d.ts +17 -5
  65. package/lib/batch.d.ts.map +1 -1
  66. package/lib/collectionHandlers.d.ts +21 -0
  67. package/lib/collectionHandlers.d.ts.map +1 -1
  68. package/lib/computed.d.ts +75 -27
  69. package/lib/computed.d.ts.map +1 -1
  70. package/lib/effect.d.ts +25 -0
  71. package/lib/effect.d.ts.map +1 -1
  72. package/lib/effectScope.d.ts +129 -0
  73. package/lib/effectScope.d.ts.map +1 -0
  74. package/lib/index.d.ts +6 -5
  75. package/lib/index.d.ts.map +1 -1
  76. package/lib/property.d.ts.map +1 -1
  77. package/lib/reactive.d.ts +58 -17
  78. package/lib/reactive.d.ts.map +1 -1
  79. package/lib/ref.d.ts +66 -4
  80. package/lib/ref.d.ts.map +1 -1
  81. package/lib/shared/constants.d.ts +7 -7
  82. package/lib/shared/constants.d.ts.map +1 -1
  83. package/lib/shared/general.d.ts +1 -1
  84. package/lib/shared/general.d.ts.map +1 -1
  85. package/package.json +19 -17
  86. package/src/Reactivity.ts +57 -15
  87. package/src/arrayInstrumentations.ts +406 -53
  88. package/src/baseHandlers.ts +124 -32
  89. package/src/batch.ts +38 -11
  90. package/src/collectionHandlers.ts +207 -19
  91. package/src/computed.ts +92 -43
  92. package/src/effect.ts +38 -0
  93. package/src/effectScope.ts +294 -0
  94. package/src/index.ts +6 -5
  95. package/src/property.ts +6 -0
  96. package/src/reactive.ts +67 -20
  97. 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
- * @param func 检测的可能包含响应式的函数。
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 { ComputedReactivity as ComputedDep, computed, type Computed } from './computed';
3
- export { Reactivity as Dep, forceTrack, noTrack } from './Reactivity';
4
- export { EffectReactivity as EffectDep, effect, type Effect } from './effect';
5
- export { isProxy, isReactive, reactive, type Reactive } from './reactive';
6
- export { RefReactivity, isRef, ref, type Ref } from './ref';
2
+ export { computed, type Computed } from './computed';
3
+ export { effect, 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 } from './Reactivity';
7
+ export { isRef, ref, type Ref } from './ref';
7
8
  export { toRaw } from './shared/general';
8
9