@feng3d/reactivity 1.0.3 → 1.0.5

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/src/computed.ts CHANGED
@@ -1,201 +1,204 @@
1
- import { batch } from './batch';
2
- import { Reactivity, ReactivityLink, forceTrack } from './Reactivity';
3
- import { hasChanged } from './shared/general';
4
-
5
- /**
6
- * 创建计算反应式对象。
7
- *
8
- * 首次获取值将会执行函数,后续获取值且在依赖发生变化的情况下将会重新计算。
9
- *
10
- * @param func 检测的可能包含响应式的函数。
11
- * @returns 包含 value 属性的对象,用于获取计算结果。
12
- */
13
- export function computed<T>(func: (oldValue?: T) => T): Computed<T>
14
- {
15
- return new ComputedReactivity(func) as any;
16
- }
17
-
18
- /**
19
- * 计算反应式对象。
20
- */
21
- export interface Computed<T = any>
22
- {
23
- readonly value: T
24
- [ComputedSymbol]: true
25
- }
26
- declare const ComputedSymbol: unique symbol;
27
-
28
- export interface ComputedReactivity<T = any> extends Computed<T> { }
29
-
30
- /**
31
- * 计算反应式节点。
32
- *
33
- * 当使用 computed 函数时,会创建一个 ComputedDep 对象。
34
- *
35
- * 首次获取值将会执行函数,后续获取值且在依赖发生变化的情况下将会重新计算。
36
- */
37
- export class ComputedReactivity<T = any> extends Reactivity<T>
38
- {
39
- /**
40
- * @internal
41
- */
42
- readonly __v_isRef = true;
43
-
44
- /**
45
- * 监听的函数。
46
- */
47
- protected _func: (oldValue?: T) => T;
48
-
49
- /**
50
- * 失效子节点。
51
- *
52
- * @private
53
- */
54
- _children = new Map<Reactivity, any>();
55
-
56
- /**
57
- * 是否脏,是否需要重新计算。
58
- *
59
- * 用于在没有值发生变化时,避免重复计算。
60
- *
61
- * @private
62
- */
63
- _isDirty = true;
64
-
65
- /**
66
- * 版本号。
67
- *
68
- * 重新计算后自动递增。用于判断子节点中的父节点引用是否过期。
69
- *
70
- * @private
71
- */
72
- _version = -1;
73
-
74
- /**
75
- * 创建计算依赖。
76
- * @param func 检测的可能包含响应式的函数。
77
- */
78
- constructor(func: (oldValue?: T) => T)
79
- {
80
- super();
81
- this._func = func;
82
- }
83
-
84
- /**
85
- * 捕捉。
86
- *
87
- * 建立与父节点的依赖关系。
88
- */
89
- track()
90
- {
91
- this.runIfDirty();
92
-
93
- super.track();
94
- }
95
-
96
- /**
97
- * 触发。
98
- *
99
- * 冒泡到所有父节点,设置失效子节点字典。
100
- *
101
- * 把触发节点添加到失效子节点字典队列中。
102
- */
103
- trigger(): void
104
- {
105
- // 正在运行时被触发,需要在运行结束后修复父子节点关系。
106
- if (Reactivity.activeReactivity === this)
107
- {
108
- batch(this, Reactivity.activeReactivity === this);
109
- }
110
-
111
- super.trigger();
112
- }
113
-
114
- /**
115
- * 执行当前节点。
116
- */
117
- run()
118
- {
119
- // 不受嵌套的 effect 影响。
120
- forceTrack(() =>
121
- {
122
- // 保存当前节点作为父节点。
123
- const parentReactiveNode = Reactivity.activeReactivity;
124
- // 设置当前节点为活跃节点。
125
- Reactivity.activeReactivity = this as any;
126
-
127
- this._version++;
128
- this._value = this._func(this._value);
129
-
130
- // 执行完毕后恢复父节点。
131
- Reactivity.activeReactivity = parentReactiveNode;
132
- });
133
- }
134
-
135
- /**
136
- * 检查当前节点是否脏。
137
- *
138
- * 如果脏,则执行计算。
139
- */
140
- runIfDirty()
141
- {
142
- // 检查是否存在失效子节点字典。
143
- this._isDirty = this._isDirty || this.isChildrenChanged();
144
-
145
- // 标记为脏的情况下,执行计算。
146
- if (this._isDirty)
147
- {
148
- // 立即去除脏标记,避免循环多重计算。
149
- this._isDirty = false;
150
-
151
- //
152
- this.run();
153
- }
154
- }
155
-
156
- /**
157
- * 判断子节点是否发生变化。
158
- */
159
- protected isChildrenChanged()
160
- {
161
- if (this._children.size === 0) return false;
162
-
163
- // 检查是否存在子节点发生变化。
164
- let isChanged = false;
165
-
166
- // 避免在检查过程建立依赖关系。
167
- const preReactiveNode = Reactivity.activeReactivity;
168
- Reactivity.activeReactivity = null;
169
-
170
- // 检查子节点是否发生变化。
171
- this._children.forEach((value, node) =>
172
- {
173
- if (isChanged) return;
174
- if (node.value !== value)
175
- {
176
- // 子节点变化,需要重新计算。
177
- isChanged = true;
178
-
179
- return;
180
- }
181
- });
182
-
183
- // 恢复父节点。
184
- Reactivity.activeReactivity = preReactiveNode;
185
-
186
- if (!isChanged)
187
- {
188
- // 修复与子节点关系
189
- this._children.forEach((version, node) =>
190
- {
191
- node._parents.set(this, this._version);
192
- });
193
- }
194
-
195
- // 清空子节点。
196
- this._children.clear();
197
-
198
- return isChanged;
199
- }
200
- }
201
-
1
+ import { batch } from './batch';
2
+ import { Reactivity, forceTrack } from './Reactivity';
3
+
4
+ /**
5
+ * 创建计算反应式对象。
6
+ *
7
+ * 首次获取值将会执行函数,后续获取值且在依赖发生变化的情况下将会重新计算。
8
+ *
9
+ * @param func 检测的可能包含响应式的函数。
10
+ * @returns 包含 value 属性的对象,用于获取计算结果。
11
+ */
12
+ export function computed<T>(func: (oldValue?: T) => T): Computed<T>
13
+ {
14
+ return new ComputedReactivity(func) as any;
15
+ }
16
+
17
+ /**
18
+ * 计算反应式对象。
19
+ */
20
+ export interface Computed<T = any>
21
+ {
22
+ readonly value: T
23
+ [ComputedSymbol]: true
24
+ }
25
+ declare const ComputedSymbol: unique symbol;
26
+
27
+ export interface ComputedReactivity<T = any> extends Computed<T> { }
28
+
29
+ /**
30
+ * 计算反应式节点。
31
+ *
32
+ * 当使用 computed 函数时,会创建一个 ComputedDep 对象。
33
+ *
34
+ * 首次获取值将会执行函数,后续获取值且在依赖发生变化的情况下将会重新计算。
35
+ */
36
+ export class ComputedReactivity<T = any> extends Reactivity<T>
37
+ {
38
+ /**
39
+ * @internal
40
+ */
41
+ readonly __v_isRef = true;
42
+
43
+ /**
44
+ * 监听的函数。
45
+ */
46
+ protected _func: (oldValue?: T) => T;
47
+
48
+ /**
49
+ * 失效子节点。
50
+ *
51
+ * @private
52
+ */
53
+ _children = new Map<Reactivity, any>();
54
+
55
+ /**
56
+ * 是否脏,是否需要重新计算。
57
+ *
58
+ * 用于在没有值发生变化时,避免重复计算。
59
+ *
60
+ * @private
61
+ */
62
+ _isDirty = true;
63
+
64
+ /**
65
+ * 版本号。
66
+ *
67
+ * 重新计算后自动递增。用于判断子节点中的父节点引用是否过期。
68
+ *
69
+ * @private
70
+ */
71
+ _version = -1;
72
+
73
+ /**
74
+ * 获取值。
75
+ *
76
+ * 取值时将会建立与父节点的依赖关系。
77
+ *
78
+ * 同时会检查子节点是否发生变化,如果发生变化,则重新计算。
79
+ */
80
+ get value(): T
81
+ {
82
+ this.runIfDirty();
83
+
84
+ this.track();
85
+
86
+ return this._value;
87
+ }
88
+
89
+ /**
90
+ * 创建计算依赖。
91
+ * @param func 检测的可能包含响应式的函数。
92
+ */
93
+ constructor(func: (oldValue?: T) => T)
94
+ {
95
+ super();
96
+ this._func = func;
97
+ }
98
+
99
+ /**
100
+ * 触发。
101
+ *
102
+ * 冒泡到所有父节点,设置失效子节点字典。
103
+ *
104
+ * 把触发节点添加到失效子节点字典队列中。
105
+ */
106
+ trigger(): void
107
+ {
108
+ // 正在运行时被触发,需要在运行结束后修复父子节点关系。
109
+ if (Reactivity.activeReactivity === this)
110
+ {
111
+ batch(this, Reactivity.activeReactivity === this);
112
+ }
113
+
114
+ super.trigger();
115
+ }
116
+
117
+ /**
118
+ * 执行当前节点。
119
+ */
120
+ run()
121
+ {
122
+ // 不受嵌套的 effect 影响。
123
+ forceTrack(() =>
124
+ {
125
+ // 保存当前节点作为父节点。
126
+ const parentReactiveNode = Reactivity.activeReactivity;
127
+ // 设置当前节点为活跃节点。
128
+ Reactivity.activeReactivity = this as any;
129
+
130
+ this._version++;
131
+ this._value = this._func(this._value);
132
+
133
+ // 执行完毕后恢复父节点。
134
+ Reactivity.activeReactivity = parentReactiveNode;
135
+ });
136
+ }
137
+
138
+ /**
139
+ * 检查当前节点是否脏。
140
+ *
141
+ * 如果脏,则执行计算。
142
+ */
143
+ runIfDirty()
144
+ {
145
+ // 检查是否存在失效子节点字典。
146
+ this._isDirty = this._isDirty || this.isChildrenChanged();
147
+
148
+ // 标记为脏的情况下,执行计算。
149
+ if (this._isDirty)
150
+ {
151
+ // 立即去除脏标记,避免循环多重计算。
152
+ this._isDirty = false;
153
+
154
+ //
155
+ this.run();
156
+ }
157
+ }
158
+
159
+ /**
160
+ * 判断子节点是否发生变化。
161
+ */
162
+ protected isChildrenChanged()
163
+ {
164
+ if (this._children.size === 0) return false;
165
+
166
+ // 检查是否存在子节点发生变化。
167
+ let isChanged = false;
168
+
169
+ // 避免在检查过程建立依赖关系。
170
+ const preReactiveNode = Reactivity.activeReactivity;
171
+ Reactivity.activeReactivity = null;
172
+
173
+ // 检查子节点是否发生变化。
174
+ this._children.forEach((value, node) =>
175
+ {
176
+ if (isChanged) return;
177
+ if (node.value !== value)
178
+ {
179
+ // 子节点变化,需要重新计算。
180
+ isChanged = true;
181
+
182
+ return;
183
+ }
184
+ });
185
+
186
+ // 恢复父节点。
187
+ Reactivity.activeReactivity = preReactiveNode;
188
+
189
+ if (!isChanged)
190
+ {
191
+ // 修复与子节点关系
192
+ this._children.forEach((version, node) =>
193
+ {
194
+ node._parents.set(this, this._version);
195
+ });
196
+ }
197
+
198
+ // 清空子节点。
199
+ this._children.clear();
200
+
201
+ return isChanged;
202
+ }
203
+ }
204
+
package/src/effect.ts CHANGED
@@ -1,108 +1,108 @@
1
- import { batch, batchRun } from './batch';
2
- import { ComputedReactivity } from './computed';
3
- import { Reactivity } from './Reactivity';
4
-
5
- /**
6
- * 创建效果反应式节点。
7
- *
8
- * 将会维持反应式效果,当被作用的函数所引用的响应式对象发生变化时,会立即执行 fn 函数。
9
- *
10
- * @param fn 要执行的函数
11
- * @returns 暂停和恢复副作用的函数
12
- *
13
- * 注:
14
- * 1. 与 `@vue/reactivity` 中的 effect 不同,此函数返回的是一个 Effect 对象,而不是一个函数。
15
- * 2. 不希望用户直接执行,而是通过反应式自动触发。
16
- * 3. 真有需求,可以使用 effect(func).run(true) 来代替 @vue/reactivity 中的 effect(func)() 。
17
- *
18
- */
19
- export function effect<T = any>(fn: () => T): Effect
20
- {
21
- return new EffectReactivity(fn);
22
- }
23
-
24
- /**
25
- * 效果反应式节点。
26
- */
27
- export class EffectReactivity<T = any> extends ComputedReactivity<T> implements Effect
28
- {
29
- /**
30
- * 是否为启用, 默认为 true。
31
- *
32
- * 启用时,会立即执行函数。
33
- */
34
- private _isEnable = true;
35
-
36
- constructor(func: (oldValue?: T) => T)
37
- {
38
- super(func);
39
- this.runIfDirty();
40
- }
41
-
42
- pause()
43
- {
44
- this._isEnable = false;
45
- }
46
-
47
- resume()
48
- {
49
- if (this._isEnable) return;
50
- this._isEnable = true;
51
- if (EffectReactivity.pausedQueueEffects.has(this))
52
- {
53
- EffectReactivity.pausedQueueEffects.delete(this);
54
- this.trigger();
55
- }
56
- }
57
-
58
- trigger()
59
- {
60
- batchRun(() =>
61
- {
62
- super.trigger();
63
-
64
- if (this._isEnable)
65
- {
66
- // 合批时需要判断是否已经运行的依赖。
67
- batch(this, Reactivity.activeReactivity === this);
68
- }
69
- else
70
- {
71
- EffectReactivity.pausedQueueEffects.add(this);
72
- }
73
- });
74
- }
75
- private static pausedQueueEffects = new WeakSet<EffectReactivity>();
76
-
77
- /**
78
- * 执行当前节点。
79
- *
80
- * 当暂停时将会直接执行被包装的函数。
81
- */
82
- run(): void
83
- {
84
- if (this._isEnable)
85
- {
86
- super.run();
87
- }
88
- else
89
- {
90
- this._func(this._value);
91
- }
92
- }
93
- }
94
-
95
- /**
96
- * 维持反应式效果。
97
- */
98
- export interface Effect
99
- {
100
- /**
101
- * 暂停。
102
- */
103
- pause: () => void;
104
- /**
105
- * 恢复。
106
- */
107
- resume: () => void;
108
- }
1
+ import { batch, batchRun } from './batch';
2
+ import { ComputedReactivity } from './computed';
3
+ import { Reactivity } from './Reactivity';
4
+
5
+ /**
6
+ * 创建效果反应式节点。
7
+ *
8
+ * 将会维持反应式效果,当被作用的函数所引用的响应式对象发生变化时,会立即执行 fn 函数。
9
+ *
10
+ * @param fn 要执行的函数
11
+ * @returns 暂停和恢复副作用的函数
12
+ *
13
+ * 注:
14
+ * 1. 与 `@vue/reactivity` 中的 effect 不同,此函数返回的是一个 Effect 对象,而不是一个函数。
15
+ * 2. 不希望用户直接执行,而是通过反应式自动触发。
16
+ * 3. 真有需求,可以使用 effect(func).run(true) 来代替 @vue/reactivity 中的 effect(func)() 。
17
+ *
18
+ */
19
+ export function effect<T = any>(fn: () => T): Effect
20
+ {
21
+ return new EffectReactivity(fn);
22
+ }
23
+
24
+ /**
25
+ * 效果反应式节点。
26
+ */
27
+ export class EffectReactivity<T = any> extends ComputedReactivity<T> implements Effect
28
+ {
29
+ /**
30
+ * 是否为启用, 默认为 true。
31
+ *
32
+ * 启用时,会立即执行函数。
33
+ */
34
+ private _isEnable = true;
35
+
36
+ constructor(func: (oldValue?: T) => T)
37
+ {
38
+ super(func);
39
+ this.runIfDirty();
40
+ }
41
+
42
+ pause()
43
+ {
44
+ this._isEnable = false;
45
+ }
46
+
47
+ resume()
48
+ {
49
+ if (this._isEnable) return;
50
+ this._isEnable = true;
51
+ if (EffectReactivity.pausedQueueEffects.has(this))
52
+ {
53
+ EffectReactivity.pausedQueueEffects.delete(this);
54
+ this.trigger();
55
+ }
56
+ }
57
+
58
+ trigger()
59
+ {
60
+ batchRun(() =>
61
+ {
62
+ super.trigger();
63
+
64
+ if (this._isEnable)
65
+ {
66
+ // 合批时需要判断是否已经运行的依赖。
67
+ batch(this, Reactivity.activeReactivity === this);
68
+ }
69
+ else
70
+ {
71
+ EffectReactivity.pausedQueueEffects.add(this);
72
+ }
73
+ });
74
+ }
75
+ private static pausedQueueEffects = new WeakSet<EffectReactivity>();
76
+
77
+ /**
78
+ * 执行当前节点。
79
+ *
80
+ * 当暂停时将会直接执行被包装的函数。
81
+ */
82
+ run(): void
83
+ {
84
+ if (this._isEnable)
85
+ {
86
+ super.run();
87
+ }
88
+ else
89
+ {
90
+ this._func(this._value);
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * 维持反应式效果。
97
+ */
98
+ export interface Effect
99
+ {
100
+ /**
101
+ * 暂停。
102
+ */
103
+ pause: () => void;
104
+ /**
105
+ * 恢复。
106
+ */
107
+ resume: () => void;
108
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
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';
7
- export { toRaw } from './shared/general';
8
-
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';
7
+ export { toRaw } from './shared/general';
8
+