@feng3d/reactivity 1.0.4 → 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/LICENSE +21 -21
- package/README.md +158 -158
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/lib/reactive.d.ts +10 -2
- package/lib/reactive.d.ts.map +1 -1
- package/package.json +66 -66
- package/src/Reactivity.ts +126 -126
- package/src/arrayInstrumentations.ts +448 -448
- package/src/baseHandlers.ts +220 -220
- package/src/batch.ts +91 -91
- package/src/collectionHandlers.ts +298 -298
- package/src/computed.ts +204 -204
- package/src/effect.ts +108 -108
- package/src/index.ts +8 -8
- package/src/property.ts +225 -225
- package/src/reactive.ts +139 -130
- package/src/ref.ts +88 -88
- package/src/shared/constants.ts +41 -41
- package/src/shared/general.ts +109 -109
- package/tsconfig.json +19 -19
package/src/baseHandlers.ts
CHANGED
|
@@ -1,220 +1,220 @@
|
|
|
1
|
-
import { arrayInstrumentations } from './arrayInstrumentations';
|
|
2
|
-
import { reactive, reactiveMap } from './reactive';
|
|
3
|
-
import { isRef } from './ref';
|
|
4
|
-
import { ITERATE_KEY, ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './shared/constants';
|
|
5
|
-
import { hasChanged, hasOwn, isArray, isIntegerKey, isObject, isSymbol, makeMap, Target, toRaw } from './shared/general';
|
|
6
|
-
import { PropertyReactivity } from './property';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 基础响应式处理器。
|
|
10
|
-
*/
|
|
11
|
-
class BaseReactiveHandler implements ProxyHandler<Target>
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* 获取对象的属性值。
|
|
15
|
-
*
|
|
16
|
-
* @param target 对象本身
|
|
17
|
-
* @param key 属性名
|
|
18
|
-
* @param receiver 代理对象
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
get(target: Target, key: string | symbol, receiver: object): any
|
|
22
|
-
{
|
|
23
|
-
//
|
|
24
|
-
if (key === ReactiveFlags.IS_REACTIVE) // 判断是否为响应式对象
|
|
25
|
-
{
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
else if (key === ReactiveFlags.RAW) // 获取原始对象
|
|
29
|
-
{
|
|
30
|
-
if (
|
|
31
|
-
receiver
|
|
32
|
-
=== reactiveMap.get(target)
|
|
33
|
-
// receiver is not the reactive proxy, but has the same prototype
|
|
34
|
-
// this means the receiver is a user proxy of the reactive proxy
|
|
35
|
-
|| Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)
|
|
36
|
-
)
|
|
37
|
-
{
|
|
38
|
-
return target;
|
|
39
|
-
}
|
|
40
|
-
// early return undefined
|
|
41
|
-
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const targetIsArray = isArray(target);
|
|
46
|
-
|
|
47
|
-
let fn: Function | undefined;
|
|
48
|
-
if (targetIsArray && (fn = arrayInstrumentations[key]))
|
|
49
|
-
{
|
|
50
|
-
return fn;
|
|
51
|
-
}
|
|
52
|
-
if (key === 'hasOwnProperty')
|
|
53
|
-
{
|
|
54
|
-
return hasOwnProperty;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const res = Reflect.get(
|
|
58
|
-
target,
|
|
59
|
-
key,
|
|
60
|
-
isRef(target) ? target : receiver,
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key))
|
|
64
|
-
{
|
|
65
|
-
return res;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
PropertyReactivity.track(target, TrackOpTypes.GET, key as any);
|
|
70
|
-
|
|
71
|
-
// 如果是 ref,则返回 ref.value
|
|
72
|
-
if (isRef(res))
|
|
73
|
-
{
|
|
74
|
-
return targetIsArray && isIntegerKey(key) ? res : res.value;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 如果是对象,则递归响应式化
|
|
78
|
-
if (isObject(res))
|
|
79
|
-
{
|
|
80
|
-
return reactive(res);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return res;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 可变响应式处理器。
|
|
89
|
-
*/
|
|
90
|
-
class MutableReactiveHandler extends BaseReactiveHandler
|
|
91
|
-
{
|
|
92
|
-
/**
|
|
93
|
-
* 设置对象的属性值。
|
|
94
|
-
* @param target 被代理的对象。
|
|
95
|
-
* @param key 属性名。
|
|
96
|
-
* @param value 新值。
|
|
97
|
-
* @param receiver 代理对象。
|
|
98
|
-
* @returns 设置是否成功。
|
|
99
|
-
*/
|
|
100
|
-
set(
|
|
101
|
-
target: Record<string | symbol, unknown>,
|
|
102
|
-
key: string | symbol,
|
|
103
|
-
value: unknown,
|
|
104
|
-
receiver: object,
|
|
105
|
-
): boolean
|
|
106
|
-
{
|
|
107
|
-
let oldValue = target[key];
|
|
108
|
-
|
|
109
|
-
oldValue = toRaw(oldValue);
|
|
110
|
-
value = toRaw(value);
|
|
111
|
-
|
|
112
|
-
if (!isArray(target) && isRef(oldValue) && !isRef(value))
|
|
113
|
-
{
|
|
114
|
-
oldValue.value = value;
|
|
115
|
-
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const hadKey
|
|
120
|
-
= isArray(target) && isIntegerKey(key)
|
|
121
|
-
? Number(key) < target.length
|
|
122
|
-
: hasOwn(target, key);
|
|
123
|
-
const result = Reflect.set(
|
|
124
|
-
target,
|
|
125
|
-
key,
|
|
126
|
-
value,
|
|
127
|
-
isRef(target) ? target : receiver,
|
|
128
|
-
);
|
|
129
|
-
//
|
|
130
|
-
__DEV__ && console.assert(target === toRaw(receiver));
|
|
131
|
-
|
|
132
|
-
// 如果目标在原始原型链中,则不要触发
|
|
133
|
-
if (target === toRaw(receiver))
|
|
134
|
-
{
|
|
135
|
-
if (!hadKey)
|
|
136
|
-
{
|
|
137
|
-
PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
|
|
138
|
-
}
|
|
139
|
-
else if (hasChanged(value, oldValue))
|
|
140
|
-
{
|
|
141
|
-
PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return result;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* 删除对象的属性。
|
|
150
|
-
*
|
|
151
|
-
* @param target 被代理的对象。
|
|
152
|
-
* @param key 属性名。
|
|
153
|
-
* @returns 删除是否成功。
|
|
154
|
-
*/
|
|
155
|
-
deleteProperty(
|
|
156
|
-
target: Record<string | symbol, unknown>,
|
|
157
|
-
key: string | symbol,
|
|
158
|
-
): boolean
|
|
159
|
-
{
|
|
160
|
-
const hadKey = hasOwn(target, key);
|
|
161
|
-
const oldValue = target[key];
|
|
162
|
-
const result = Reflect.deleteProperty(target, key);
|
|
163
|
-
if (result && hadKey)
|
|
164
|
-
{
|
|
165
|
-
PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return result;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
has(target: Record<string | symbol, unknown>, key: string | symbol): boolean
|
|
172
|
-
{
|
|
173
|
-
const result = Reflect.has(target, key);
|
|
174
|
-
if (!isSymbol(key) || !builtInSymbols.has(key))
|
|
175
|
-
{
|
|
176
|
-
PropertyReactivity.track(target, TrackOpTypes.HAS, key);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return result;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
ownKeys(target: Record<string | symbol, unknown>): (string | symbol)[]
|
|
183
|
-
{
|
|
184
|
-
PropertyReactivity.track(
|
|
185
|
-
target,
|
|
186
|
-
TrackOpTypes.ITERATE,
|
|
187
|
-
isArray(target) ? 'length' : ITERATE_KEY,
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
return Reflect.ownKeys(target);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* 可变响应式处理器。
|
|
196
|
-
*/
|
|
197
|
-
export const mutableHandlers: ProxyHandler<object> = new MutableReactiveHandler();
|
|
198
|
-
|
|
199
|
-
function hasOwnProperty(this: object, key: unknown)
|
|
200
|
-
{
|
|
201
|
-
// #10455 hasOwnProperty may be called with non-string values
|
|
202
|
-
if (!isSymbol(key)) key = String(key);
|
|
203
|
-
const obj = toRaw(this);
|
|
204
|
-
PropertyReactivity.track(obj, TrackOpTypes.HAS, key);
|
|
205
|
-
|
|
206
|
-
return obj.hasOwnProperty(key as string);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const builtInSymbols = new Set(
|
|
210
|
-
/* @__PURE__*/
|
|
211
|
-
Object.getOwnPropertyNames(Symbol)
|
|
212
|
-
// ios10.x Object.getOwnPropertyNames(Symbol) can enumerate 'arguments' and 'caller'
|
|
213
|
-
// but accessing them on Symbol leads to TypeError because Symbol is a strict mode
|
|
214
|
-
// function
|
|
215
|
-
.filter((key) => key !== 'arguments' && key !== 'caller')
|
|
216
|
-
.map((key) => Symbol[key as keyof SymbolConstructor])
|
|
217
|
-
.filter(isSymbol),
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
const isNonTrackableKeys = /* @__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
|
|
1
|
+
import { arrayInstrumentations } from './arrayInstrumentations';
|
|
2
|
+
import { reactive, reactiveMap } from './reactive';
|
|
3
|
+
import { isRef } from './ref';
|
|
4
|
+
import { ITERATE_KEY, ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './shared/constants';
|
|
5
|
+
import { hasChanged, hasOwn, isArray, isIntegerKey, isObject, isSymbol, makeMap, Target, toRaw } from './shared/general';
|
|
6
|
+
import { PropertyReactivity } from './property';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 基础响应式处理器。
|
|
10
|
+
*/
|
|
11
|
+
class BaseReactiveHandler implements ProxyHandler<Target>
|
|
12
|
+
{
|
|
13
|
+
/**
|
|
14
|
+
* 获取对象的属性值。
|
|
15
|
+
*
|
|
16
|
+
* @param target 对象本身
|
|
17
|
+
* @param key 属性名
|
|
18
|
+
* @param receiver 代理对象
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
get(target: Target, key: string | symbol, receiver: object): any
|
|
22
|
+
{
|
|
23
|
+
//
|
|
24
|
+
if (key === ReactiveFlags.IS_REACTIVE) // 判断是否为响应式对象
|
|
25
|
+
{
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
else if (key === ReactiveFlags.RAW) // 获取原始对象
|
|
29
|
+
{
|
|
30
|
+
if (
|
|
31
|
+
receiver
|
|
32
|
+
=== reactiveMap.get(target)
|
|
33
|
+
// receiver is not the reactive proxy, but has the same prototype
|
|
34
|
+
// this means the receiver is a user proxy of the reactive proxy
|
|
35
|
+
|| Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)
|
|
36
|
+
)
|
|
37
|
+
{
|
|
38
|
+
return target;
|
|
39
|
+
}
|
|
40
|
+
// early return undefined
|
|
41
|
+
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const targetIsArray = isArray(target);
|
|
46
|
+
|
|
47
|
+
let fn: Function | undefined;
|
|
48
|
+
if (targetIsArray && (fn = arrayInstrumentations[key]))
|
|
49
|
+
{
|
|
50
|
+
return fn;
|
|
51
|
+
}
|
|
52
|
+
if (key === 'hasOwnProperty')
|
|
53
|
+
{
|
|
54
|
+
return hasOwnProperty;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const res = Reflect.get(
|
|
58
|
+
target,
|
|
59
|
+
key,
|
|
60
|
+
isRef(target) ? target : receiver,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key))
|
|
64
|
+
{
|
|
65
|
+
return res;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//
|
|
69
|
+
PropertyReactivity.track(target, TrackOpTypes.GET, key as any);
|
|
70
|
+
|
|
71
|
+
// 如果是 ref,则返回 ref.value
|
|
72
|
+
if (isRef(res))
|
|
73
|
+
{
|
|
74
|
+
return targetIsArray && isIntegerKey(key) ? res : res.value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 如果是对象,则递归响应式化
|
|
78
|
+
if (isObject(res))
|
|
79
|
+
{
|
|
80
|
+
return reactive(res);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 可变响应式处理器。
|
|
89
|
+
*/
|
|
90
|
+
class MutableReactiveHandler extends BaseReactiveHandler
|
|
91
|
+
{
|
|
92
|
+
/**
|
|
93
|
+
* 设置对象的属性值。
|
|
94
|
+
* @param target 被代理的对象。
|
|
95
|
+
* @param key 属性名。
|
|
96
|
+
* @param value 新值。
|
|
97
|
+
* @param receiver 代理对象。
|
|
98
|
+
* @returns 设置是否成功。
|
|
99
|
+
*/
|
|
100
|
+
set(
|
|
101
|
+
target: Record<string | symbol, unknown>,
|
|
102
|
+
key: string | symbol,
|
|
103
|
+
value: unknown,
|
|
104
|
+
receiver: object,
|
|
105
|
+
): boolean
|
|
106
|
+
{
|
|
107
|
+
let oldValue = target[key];
|
|
108
|
+
|
|
109
|
+
oldValue = toRaw(oldValue);
|
|
110
|
+
value = toRaw(value);
|
|
111
|
+
|
|
112
|
+
if (!isArray(target) && isRef(oldValue) && !isRef(value))
|
|
113
|
+
{
|
|
114
|
+
oldValue.value = value;
|
|
115
|
+
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const hadKey
|
|
120
|
+
= isArray(target) && isIntegerKey(key)
|
|
121
|
+
? Number(key) < target.length
|
|
122
|
+
: hasOwn(target, key);
|
|
123
|
+
const result = Reflect.set(
|
|
124
|
+
target,
|
|
125
|
+
key,
|
|
126
|
+
value,
|
|
127
|
+
isRef(target) ? target : receiver,
|
|
128
|
+
);
|
|
129
|
+
//
|
|
130
|
+
__DEV__ && console.assert(target === toRaw(receiver));
|
|
131
|
+
|
|
132
|
+
// 如果目标在原始原型链中,则不要触发
|
|
133
|
+
if (target === toRaw(receiver))
|
|
134
|
+
{
|
|
135
|
+
if (!hadKey)
|
|
136
|
+
{
|
|
137
|
+
PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
|
|
138
|
+
}
|
|
139
|
+
else if (hasChanged(value, oldValue))
|
|
140
|
+
{
|
|
141
|
+
PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 删除对象的属性。
|
|
150
|
+
*
|
|
151
|
+
* @param target 被代理的对象。
|
|
152
|
+
* @param key 属性名。
|
|
153
|
+
* @returns 删除是否成功。
|
|
154
|
+
*/
|
|
155
|
+
deleteProperty(
|
|
156
|
+
target: Record<string | symbol, unknown>,
|
|
157
|
+
key: string | symbol,
|
|
158
|
+
): boolean
|
|
159
|
+
{
|
|
160
|
+
const hadKey = hasOwn(target, key);
|
|
161
|
+
const oldValue = target[key];
|
|
162
|
+
const result = Reflect.deleteProperty(target, key);
|
|
163
|
+
if (result && hadKey)
|
|
164
|
+
{
|
|
165
|
+
PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
has(target: Record<string | symbol, unknown>, key: string | symbol): boolean
|
|
172
|
+
{
|
|
173
|
+
const result = Reflect.has(target, key);
|
|
174
|
+
if (!isSymbol(key) || !builtInSymbols.has(key))
|
|
175
|
+
{
|
|
176
|
+
PropertyReactivity.track(target, TrackOpTypes.HAS, key);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
ownKeys(target: Record<string | symbol, unknown>): (string | symbol)[]
|
|
183
|
+
{
|
|
184
|
+
PropertyReactivity.track(
|
|
185
|
+
target,
|
|
186
|
+
TrackOpTypes.ITERATE,
|
|
187
|
+
isArray(target) ? 'length' : ITERATE_KEY,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
return Reflect.ownKeys(target);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 可变响应式处理器。
|
|
196
|
+
*/
|
|
197
|
+
export const mutableHandlers: ProxyHandler<object> = new MutableReactiveHandler();
|
|
198
|
+
|
|
199
|
+
function hasOwnProperty(this: object, key: unknown)
|
|
200
|
+
{
|
|
201
|
+
// #10455 hasOwnProperty may be called with non-string values
|
|
202
|
+
if (!isSymbol(key)) key = String(key);
|
|
203
|
+
const obj = toRaw(this);
|
|
204
|
+
PropertyReactivity.track(obj, TrackOpTypes.HAS, key);
|
|
205
|
+
|
|
206
|
+
return obj.hasOwnProperty(key as string);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const builtInSymbols = new Set(
|
|
210
|
+
/* @__PURE__*/
|
|
211
|
+
Object.getOwnPropertyNames(Symbol)
|
|
212
|
+
// ios10.x Object.getOwnPropertyNames(Symbol) can enumerate 'arguments' and 'caller'
|
|
213
|
+
// but accessing them on Symbol leads to TypeError because Symbol is a strict mode
|
|
214
|
+
// function
|
|
215
|
+
.filter((key) => key !== 'arguments' && key !== 'caller')
|
|
216
|
+
.map((key) => Symbol[key as keyof SymbolConstructor])
|
|
217
|
+
.filter(isSymbol),
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const isNonTrackableKeys = /* @__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
|
package/src/batch.ts
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
import { ComputedReactivity } from './computed';
|
|
2
|
-
import { Reactivity } from './Reactivity';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 合批处理。
|
|
6
|
-
*
|
|
7
|
-
* @param dep 要处理的依赖。
|
|
8
|
-
* @param isRunning 添加时是否是正在运行。
|
|
9
|
-
*/
|
|
10
|
-
export function batch(dep: ComputedReactivity, isRunning: boolean): void
|
|
11
|
-
{
|
|
12
|
-
if (isRunning)
|
|
13
|
-
{
|
|
14
|
-
_isRunedDeps.push(dep);
|
|
15
|
-
}
|
|
16
|
-
else
|
|
17
|
-
{
|
|
18
|
-
_needEffectDeps.push(dep);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 批次执行多次修改反应式对象,可以减少不必要的反应式触发。
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
* batchRun(() => {
|
|
27
|
-
* // 修改反应式对象
|
|
28
|
-
* reactiveObj.a = 1;
|
|
29
|
-
* reactiveObj.b = 2;
|
|
30
|
-
* })
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* @param fn 要执行的函数,在此函数中多次修改反应式对象。
|
|
34
|
-
*/
|
|
35
|
-
export function batchRun<T>(fn: () => T): T
|
|
36
|
-
{
|
|
37
|
-
_batchDepth++;
|
|
38
|
-
|
|
39
|
-
const result = fn();
|
|
40
|
-
|
|
41
|
-
if (--_batchDepth > 0)
|
|
42
|
-
{
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// 处理已经运行过的依赖,
|
|
47
|
-
if (_isRunedDeps.length > 0)
|
|
48
|
-
{
|
|
49
|
-
_isRunedDeps.forEach((dep) =>
|
|
50
|
-
{
|
|
51
|
-
// 此时依赖以及子依赖都已经运行过了,只需修复与子节点关系。
|
|
52
|
-
__DEV__ && console.assert(dep._isDirty === false, 'dep.dirty === false');
|
|
53
|
-
|
|
54
|
-
// 修复与子节点关系
|
|
55
|
-
dep._children.forEach((version, node) =>
|
|
56
|
-
{
|
|
57
|
-
node._parents.set(dep, dep._version);
|
|
58
|
-
});
|
|
59
|
-
dep._children.clear();
|
|
60
|
-
});
|
|
61
|
-
_isRunedDeps.length = 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// 批次处理
|
|
65
|
-
if (_needEffectDeps.length > 0)
|
|
66
|
-
{
|
|
67
|
-
_needEffectDeps.forEach((dep) =>
|
|
68
|
-
{
|
|
69
|
-
// 独立执行回调
|
|
70
|
-
const pre = Reactivity.activeReactivity;
|
|
71
|
-
Reactivity.activeReactivity = null;
|
|
72
|
-
|
|
73
|
-
dep.runIfDirty();
|
|
74
|
-
|
|
75
|
-
Reactivity.activeReactivity = pre;
|
|
76
|
-
});
|
|
77
|
-
_needEffectDeps.length = 0;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return result;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
let _batchDepth = 0;
|
|
84
|
-
/**
|
|
85
|
-
* 正在运行的依赖。
|
|
86
|
-
*/
|
|
87
|
-
const _needEffectDeps: ComputedReactivity[] = [];
|
|
88
|
-
/**
|
|
89
|
-
* 已经运行过的依赖,只需要修复与子节点关系。
|
|
90
|
-
*/
|
|
91
|
-
const _isRunedDeps: ComputedReactivity[] = [];
|
|
1
|
+
import { ComputedReactivity } from './computed';
|
|
2
|
+
import { Reactivity } from './Reactivity';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 合批处理。
|
|
6
|
+
*
|
|
7
|
+
* @param dep 要处理的依赖。
|
|
8
|
+
* @param isRunning 添加时是否是正在运行。
|
|
9
|
+
*/
|
|
10
|
+
export function batch(dep: ComputedReactivity, isRunning: boolean): void
|
|
11
|
+
{
|
|
12
|
+
if (isRunning)
|
|
13
|
+
{
|
|
14
|
+
_isRunedDeps.push(dep);
|
|
15
|
+
}
|
|
16
|
+
else
|
|
17
|
+
{
|
|
18
|
+
_needEffectDeps.push(dep);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 批次执行多次修改反应式对象,可以减少不必要的反应式触发。
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* batchRun(() => {
|
|
27
|
+
* // 修改反应式对象
|
|
28
|
+
* reactiveObj.a = 1;
|
|
29
|
+
* reactiveObj.b = 2;
|
|
30
|
+
* })
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param fn 要执行的函数,在此函数中多次修改反应式对象。
|
|
34
|
+
*/
|
|
35
|
+
export function batchRun<T>(fn: () => T): T
|
|
36
|
+
{
|
|
37
|
+
_batchDepth++;
|
|
38
|
+
|
|
39
|
+
const result = fn();
|
|
40
|
+
|
|
41
|
+
if (--_batchDepth > 0)
|
|
42
|
+
{
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 处理已经运行过的依赖,
|
|
47
|
+
if (_isRunedDeps.length > 0)
|
|
48
|
+
{
|
|
49
|
+
_isRunedDeps.forEach((dep) =>
|
|
50
|
+
{
|
|
51
|
+
// 此时依赖以及子依赖都已经运行过了,只需修复与子节点关系。
|
|
52
|
+
__DEV__ && console.assert(dep._isDirty === false, 'dep.dirty === false');
|
|
53
|
+
|
|
54
|
+
// 修复与子节点关系
|
|
55
|
+
dep._children.forEach((version, node) =>
|
|
56
|
+
{
|
|
57
|
+
node._parents.set(dep, dep._version);
|
|
58
|
+
});
|
|
59
|
+
dep._children.clear();
|
|
60
|
+
});
|
|
61
|
+
_isRunedDeps.length = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 批次处理
|
|
65
|
+
if (_needEffectDeps.length > 0)
|
|
66
|
+
{
|
|
67
|
+
_needEffectDeps.forEach((dep) =>
|
|
68
|
+
{
|
|
69
|
+
// 独立执行回调
|
|
70
|
+
const pre = Reactivity.activeReactivity;
|
|
71
|
+
Reactivity.activeReactivity = null;
|
|
72
|
+
|
|
73
|
+
dep.runIfDirty();
|
|
74
|
+
|
|
75
|
+
Reactivity.activeReactivity = pre;
|
|
76
|
+
});
|
|
77
|
+
_needEffectDeps.length = 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let _batchDepth = 0;
|
|
84
|
+
/**
|
|
85
|
+
* 正在运行的依赖。
|
|
86
|
+
*/
|
|
87
|
+
const _needEffectDeps: ComputedReactivity[] = [];
|
|
88
|
+
/**
|
|
89
|
+
* 已经运行过的依赖,只需要修复与子节点关系。
|
|
90
|
+
*/
|
|
91
|
+
const _isRunedDeps: ComputedReactivity[] = [];
|