@viewfly/core 2.1.0 → 3.0.0-alpha.0
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/README.md +67 -4
- package/dist/_utils/make-error.d.ts +1 -0
- package/dist/base/_api.d.ts +12 -0
- package/dist/base/_utils.d.ts +46 -0
- package/dist/base/component.d.ts +77 -0
- package/dist/base/context.d.ts +112 -0
- package/dist/base/dep.d.ts +9 -0
- package/dist/base/injection-tokens.d.ts +20 -0
- package/dist/base/jsx-element.d.ts +64 -0
- package/dist/base/lifecycle.d.ts +54 -0
- package/dist/base/ref.d.ts +50 -0
- package/dist/base/renderer.d.ts +4 -0
- package/dist/base/root.component.d.ts +9 -0
- package/dist/base/types.d.ts +29 -0
- package/dist/di/_api.d.ts +10 -0
- package/dist/di/forward-ref.d.ts +10 -0
- package/dist/di/injectable.d.ts +20 -0
- package/dist/di/injection-token.d.ts +8 -0
- package/dist/di/injector.d.ts +26 -0
- package/dist/di/metadata.d.ts +43 -0
- package/dist/di/null-injector.d.ts +6 -0
- package/dist/di/provider.d.ts +30 -0
- package/dist/di/reflective-injector.d.ts +30 -0
- package/dist/di/reflective-provider.d.ts +20 -0
- package/dist/di/type.d.ts +7 -0
- package/dist/di/utils/_api.d.ts +3 -0
- package/dist/di/utils/annotations.d.ts +33 -0
- package/dist/di/utils/decorators.d.ts +17 -0
- package/dist/di/utils/stringify.d.ts +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.esm.js +2302 -0
- package/dist/index.js +2940 -0
- package/dist/jsx-runtime/index.d.ts +7 -0
- package/dist/jsx-runtime/index.esm.js +2 -0
- package/dist/jsx-runtime/index.js +26 -0
- package/dist/jsx-runtime.d.ts +7 -0
- package/dist/reactive/_api.d.ts +7 -0
- package/dist/reactive/_help.d.ts +15 -0
- package/dist/reactive/array-handlers.d.ts +30 -0
- package/dist/reactive/computed.d.ts +10 -0
- package/dist/reactive/effect.d.ts +13 -0
- package/dist/reactive/iterable-iterator.d.ts +5 -0
- package/dist/reactive/map-handlers.d.ts +12 -0
- package/dist/reactive/reactive.d.ts +141 -0
- package/dist/reactive/set-handlers.d.ts +11 -0
- package/dist/reactive/shallow-reactive.d.ts +6 -0
- package/dist/reactive/signal.d.ts +38 -0
- package/dist/reactive/watch-effect.d.ts +7 -0
- package/dist/reactive/watch.d.ts +8 -0
- package/dist/viewfly.d.ts +30 -0
- package/package.json +29 -29
- package/bundles/index.d.ts +0 -768
- package/bundles/index.esm.js +0 -2700
- package/bundles/index.js +0 -2777
- package/jsx-runtime/index.d.ts +0 -25
- package/jsx-runtime/index.esm.js +0 -11
- package/jsx-runtime/index.js +0 -14
- package/jsx-runtime/package.json +0 -29
- package/rollup-d.config.ts +0 -14
|
@@ -0,0 +1,2302 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
//#region src/di/forward-ref.ts
|
|
3
|
+
var ForwardRef = class {
|
|
4
|
+
constructor(forwardRefFn) {
|
|
5
|
+
this.forwardRefFn = forwardRefFn;
|
|
6
|
+
}
|
|
7
|
+
getRef() {
|
|
8
|
+
return this.forwardRefFn();
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 引用后声明的类的工具函数
|
|
13
|
+
* @param fn
|
|
14
|
+
*/
|
|
15
|
+
function forwardRef(fn) {
|
|
16
|
+
return new ForwardRef(fn);
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/di/utils/annotations.ts
|
|
20
|
+
/**
|
|
21
|
+
* 用于保存 class 的元数据
|
|
22
|
+
*/
|
|
23
|
+
var Annotations = class {
|
|
24
|
+
classes = /* @__PURE__ */ new Map();
|
|
25
|
+
props = /* @__PURE__ */ new Map();
|
|
26
|
+
params = /* @__PURE__ */ new Map();
|
|
27
|
+
setClassMetadata(token, params) {
|
|
28
|
+
this.classes.set(token, params);
|
|
29
|
+
}
|
|
30
|
+
getClassMetadata(token) {
|
|
31
|
+
return this.classes.get(token);
|
|
32
|
+
}
|
|
33
|
+
pushParamMetadata(token, params) {
|
|
34
|
+
if (this.params.has(token)) this.params.get(token).push(params);
|
|
35
|
+
else this.params.set(token, [params]);
|
|
36
|
+
}
|
|
37
|
+
getParamMetadata(token) {
|
|
38
|
+
return this.params.get(token);
|
|
39
|
+
}
|
|
40
|
+
getPropMetadataKeys() {
|
|
41
|
+
return Array.from(this.props.keys());
|
|
42
|
+
}
|
|
43
|
+
pushPropMetadata(token, params) {
|
|
44
|
+
if (this.props.has(token)) this.props.get(token).push(params);
|
|
45
|
+
else this.props.set(token, [params]);
|
|
46
|
+
}
|
|
47
|
+
getPropMetadata(token) {
|
|
48
|
+
return this.props.get(token);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/di/utils/decorators.ts
|
|
53
|
+
/**
|
|
54
|
+
* 创建参数装饰器的工厂函数
|
|
55
|
+
*/
|
|
56
|
+
function makeParamDecorator(token, metadata) {
|
|
57
|
+
return function(target, propertyKey, parameterIndex) {
|
|
58
|
+
getAnnotations(target).pushParamMetadata(token, {
|
|
59
|
+
propertyKey,
|
|
60
|
+
parameterIndex,
|
|
61
|
+
metadata
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 创建属性装饰器的工厂函数
|
|
67
|
+
*/
|
|
68
|
+
function makePropertyDecorator(token, injectToken, contextCallback) {
|
|
69
|
+
return function(target, propertyKey) {
|
|
70
|
+
getAnnotations(target.constructor).pushPropMetadata(token, {
|
|
71
|
+
injectToken: injectToken || Reflect.getMetadata("design:type", target, propertyKey),
|
|
72
|
+
propertyKey,
|
|
73
|
+
contextCallback
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 创建类装饰器的工厂函数
|
|
79
|
+
*/
|
|
80
|
+
function makeClassDecorator(token, metadata) {
|
|
81
|
+
return function(target) {
|
|
82
|
+
getAnnotations(target).setClassMetadata(token, {
|
|
83
|
+
paramTypes: Reflect.getMetadata("design:paramtypes", target),
|
|
84
|
+
metadata
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 获取类注解的工具函数
|
|
90
|
+
*/
|
|
91
|
+
function getAnnotations(target) {
|
|
92
|
+
const key = "__annotations__";
|
|
93
|
+
if (!target.hasOwnProperty(key)) target[key] = new Annotations();
|
|
94
|
+
return target[key];
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/di/injectable.ts
|
|
98
|
+
var Scope = class {
|
|
99
|
+
constructor(name) {
|
|
100
|
+
this.name = name;
|
|
101
|
+
}
|
|
102
|
+
toString() {
|
|
103
|
+
return this.name || "[anonymous provide scope]";
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* 可注入类的装饰器
|
|
108
|
+
*/
|
|
109
|
+
var Injectable = function InjectableDecorator(options) {
|
|
110
|
+
if (this instanceof InjectableDecorator) this.provideIn = options?.provideIn || null;
|
|
111
|
+
else return makeClassDecorator(Injectable, new Injectable(options));
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/di/injection-token.ts
|
|
115
|
+
/**
|
|
116
|
+
* 生成自定义依赖注入 token 的类
|
|
117
|
+
*/
|
|
118
|
+
var InjectionToken = class {
|
|
119
|
+
constructor(description) {
|
|
120
|
+
this.description = description;
|
|
121
|
+
}
|
|
122
|
+
toString() {
|
|
123
|
+
return this.description || "[anonymous injection token]";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/di/injector.ts
|
|
128
|
+
/**
|
|
129
|
+
* 查找规则
|
|
130
|
+
*/
|
|
131
|
+
var InjectFlags = /* @__PURE__ */ function(InjectFlags) {
|
|
132
|
+
/** 默认查找规则 */
|
|
133
|
+
InjectFlags["Default"] = "Default";
|
|
134
|
+
/** 锁定当前容器 */
|
|
135
|
+
InjectFlags["Self"] = "Self";
|
|
136
|
+
/** 跳过当前容器 */
|
|
137
|
+
InjectFlags["SkipSelf"] = "SkipSelf";
|
|
138
|
+
/** 可选查找 */
|
|
139
|
+
InjectFlags["Optional"] = "Optional";
|
|
140
|
+
return InjectFlags;
|
|
141
|
+
}({});
|
|
142
|
+
/**
|
|
143
|
+
* DI 容器抽象基类
|
|
144
|
+
*/
|
|
145
|
+
var Injector = class {};
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/di/metadata.ts
|
|
148
|
+
/**
|
|
149
|
+
* 构造函数参数装饰器,用于改变注入 token
|
|
150
|
+
*/
|
|
151
|
+
var Inject = function InjectDecorator(token) {
|
|
152
|
+
if (this instanceof Inject) this.token = token;
|
|
153
|
+
else return makeParamDecorator(Inject, new Inject(token));
|
|
154
|
+
};
|
|
155
|
+
var Self = function SelfDecorator() {
|
|
156
|
+
if (!(this instanceof Self)) return makeParamDecorator(Self, new Self());
|
|
157
|
+
};
|
|
158
|
+
var SkipSelf = function SkipSelfDecorator() {
|
|
159
|
+
if (!(this instanceof SkipSelf)) return makeParamDecorator(SkipSelf, new SkipSelf());
|
|
160
|
+
};
|
|
161
|
+
var Optional = function OptionalDecorator() {
|
|
162
|
+
if (!(this instanceof Optional)) return makeParamDecorator(Optional, new Optional());
|
|
163
|
+
};
|
|
164
|
+
var Prop = function PropDecorator(token, notFoundValue, flags) {
|
|
165
|
+
if (!(this instanceof Prop)) return makePropertyDecorator(Prop, token, function(instance, propertyName, token, injector) {
|
|
166
|
+
instance[propertyName] = injector.get(token instanceof ForwardRef ? token.getRef() : token, notFoundValue, flags);
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/di/utils/stringify.ts
|
|
171
|
+
function stringify(token) {
|
|
172
|
+
if (typeof token === "string") return token;
|
|
173
|
+
if (Array.isArray(token)) return "[" + token.map(stringify).join(", ") + "]";
|
|
174
|
+
if (token == null) return "" + token;
|
|
175
|
+
if (token.name) return `${token.name}`;
|
|
176
|
+
if (token.token) return `${token.token}`;
|
|
177
|
+
const res = token.toString();
|
|
178
|
+
if (res == null) return "" + res;
|
|
179
|
+
const newLineIndex = res.indexOf("\n");
|
|
180
|
+
return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/_utils/make-error.ts
|
|
184
|
+
function makeError(name) {
|
|
185
|
+
return function viewflyError(message) {
|
|
186
|
+
const error = new Error(message);
|
|
187
|
+
error.name = `[ViewflyError: ${name}]`;
|
|
188
|
+
error.stack = error.stack.replace(/\n.*?(?=\n)/, "");
|
|
189
|
+
return error;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/di/null-injector.ts
|
|
194
|
+
var THROW_IF_NOT_FOUND = { __debug_value__: "THROW_IF_NOT_FOUND" };
|
|
195
|
+
var nullInjectorErrorFn = (token) => {
|
|
196
|
+
return makeError("NullInjector")(`No provide for \`${stringify(token)}\`!`);
|
|
197
|
+
};
|
|
198
|
+
var NullInjector = class {
|
|
199
|
+
parentInjector = null;
|
|
200
|
+
get(token, notFoundValue = THROW_IF_NOT_FOUND, _) {
|
|
201
|
+
if (notFoundValue === THROW_IF_NOT_FOUND) throw nullInjectorErrorFn(token);
|
|
202
|
+
return notFoundValue;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
//#endregion
|
|
206
|
+
//#region src/di/reflective-provider.ts
|
|
207
|
+
/**
|
|
208
|
+
* 标准化 provide,并返回统一数据结构
|
|
209
|
+
* @param provider
|
|
210
|
+
*/
|
|
211
|
+
function normalizeProvider(provider) {
|
|
212
|
+
if (provider.useValue) return normalizeValueProviderFactory(provider);
|
|
213
|
+
if (provider.useClass) return normalizeClassProviderFactory(provider);
|
|
214
|
+
if (provider.useExisting) return normalizeExistingProviderFactory(provider);
|
|
215
|
+
if (provider.useFactory) return normalizeFactoryProviderFactory(provider);
|
|
216
|
+
if (provider.provide) {
|
|
217
|
+
if (provider.provide instanceof InjectionToken) return normalizeValueProviderFactory(provider);
|
|
218
|
+
return normalizeConstructorProviderFactory(provider);
|
|
219
|
+
}
|
|
220
|
+
return normalizeTypeProviderFactory(provider);
|
|
221
|
+
}
|
|
222
|
+
function normalizeValueProviderFactory(provider) {
|
|
223
|
+
return {
|
|
224
|
+
provide: provider.provide,
|
|
225
|
+
scope: null,
|
|
226
|
+
generateFactory() {
|
|
227
|
+
return function() {
|
|
228
|
+
return provider.useValue;
|
|
229
|
+
};
|
|
230
|
+
},
|
|
231
|
+
deps: []
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function normalizeClassProviderFactory(provider) {
|
|
235
|
+
let deps;
|
|
236
|
+
let provideIn = null;
|
|
237
|
+
if (provider.deps) deps = normalizeDeps(provider.provide, provider.deps);
|
|
238
|
+
else {
|
|
239
|
+
const resolvedClass = resolveClassParams(provider.useClass);
|
|
240
|
+
provideIn = resolvedClass.scope;
|
|
241
|
+
deps = normalizeDeps(provider.provide, resolvedClass.deps);
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
provide: provider.provide,
|
|
245
|
+
scope: provideIn,
|
|
246
|
+
deps,
|
|
247
|
+
generateFactory(injector, cacheFn) {
|
|
248
|
+
return function(...args) {
|
|
249
|
+
const instance = new provider.useClass(...args);
|
|
250
|
+
cacheFn(provider.provide, instance);
|
|
251
|
+
getAnnotations(provider.useClass).getPropMetadataKeys().forEach((key) => {
|
|
252
|
+
getAnnotations(provider.useClass).getPropMetadata(key).forEach((item) => {
|
|
253
|
+
item.contextCallback(instance, item.propertyKey, item.injectToken, injector);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
return instance;
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function normalizeExistingProviderFactory(provider) {
|
|
262
|
+
return {
|
|
263
|
+
provide: provider.provide,
|
|
264
|
+
scope: null,
|
|
265
|
+
generateFactory(injector) {
|
|
266
|
+
return function() {
|
|
267
|
+
return injector.get(provider.useExisting);
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
deps: []
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function normalizeFactoryProviderFactory(provider) {
|
|
274
|
+
return {
|
|
275
|
+
provide: provider.provide,
|
|
276
|
+
scope: null,
|
|
277
|
+
generateFactory() {
|
|
278
|
+
return function(...args) {
|
|
279
|
+
return provider.useFactory(...args);
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
deps: normalizeDeps(provider.provide, provider.deps || [])
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function normalizeConstructorProviderFactory(provider) {
|
|
286
|
+
return normalizeClassProviderFactory({
|
|
287
|
+
...provider,
|
|
288
|
+
useClass: provider.provide
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function normalizeTypeProviderFactory(provider) {
|
|
292
|
+
return normalizeClassProviderFactory({
|
|
293
|
+
provide: provider,
|
|
294
|
+
useClass: provider
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function resolveClassParams(construct) {
|
|
298
|
+
const annotations = getAnnotations(construct);
|
|
299
|
+
const metadata = annotations.getClassMetadata(Injectable);
|
|
300
|
+
if (typeof metadata === "undefined") throw new Error(`Class \`${stringify(construct)}\` is not injectable!`);
|
|
301
|
+
const deps = (metadata.paramTypes || []).map((i) => [i]);
|
|
302
|
+
[
|
|
303
|
+
Inject,
|
|
304
|
+
Self,
|
|
305
|
+
SkipSelf,
|
|
306
|
+
Optional
|
|
307
|
+
].forEach((key) => {
|
|
308
|
+
(annotations.getParamMetadata(key) || []).forEach((item) => {
|
|
309
|
+
deps[item.parameterIndex].push(item.metadata);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
return {
|
|
313
|
+
scope: metadata.metadata.provideIn,
|
|
314
|
+
deps
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function normalizeDeps(provide, deps) {
|
|
318
|
+
return deps.map((dep, index) => {
|
|
319
|
+
const r = {
|
|
320
|
+
injectKey: null,
|
|
321
|
+
optional: false,
|
|
322
|
+
visibility: null
|
|
323
|
+
};
|
|
324
|
+
if (!Array.isArray(dep)) r.injectKey = dep;
|
|
325
|
+
else for (let i = 0; i < dep.length; i++) {
|
|
326
|
+
const item = dep[i];
|
|
327
|
+
if (item instanceof Inject) r.injectKey = item.token;
|
|
328
|
+
else if (item instanceof Self || item instanceof SkipSelf) r.visibility = item;
|
|
329
|
+
else if (item instanceof Optional) r.optional = true;
|
|
330
|
+
else r.injectKey = item;
|
|
331
|
+
}
|
|
332
|
+
if (typeof r.injectKey === "undefined") throw new Error(`The ${index} th dependent parameter type of \`${stringify(provide)}\` was not obtained, if the dependency is declared later, you can refer to it using \`constructor(@Inject(forwardRef(() => [Type|InjectionToken])) paramName: [Type]) {}\``);
|
|
333
|
+
return r;
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/di/reflective-injector.ts
|
|
338
|
+
var reflectiveInjectorErrorFn = (token) => {
|
|
339
|
+
return makeError("ReflectiveInjector")(`No provide for \`${stringify(token)}\`!`);
|
|
340
|
+
};
|
|
341
|
+
var provideScopeError = (token) => {
|
|
342
|
+
return makeError("ProvideScope")(`Can not found provide scope \`${stringify(token)}\`!`);
|
|
343
|
+
};
|
|
344
|
+
/**
|
|
345
|
+
* 反射注入器
|
|
346
|
+
*/
|
|
347
|
+
var ReflectiveInjector = class {
|
|
348
|
+
normalizedProviders;
|
|
349
|
+
recordValues = /* @__PURE__ */ new Map();
|
|
350
|
+
constructor(parentInjector, staticProviders, scope) {
|
|
351
|
+
this.parentInjector = parentInjector;
|
|
352
|
+
this.scope = scope;
|
|
353
|
+
this.normalizedProviders = staticProviders.map((provide) => {
|
|
354
|
+
return normalizeProvider(provide);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 用于获取当前注入器上下文内的实例、对象或数据
|
|
359
|
+
* @param token 访问 token
|
|
360
|
+
* @param notFoundValue 如未查找到的返回值
|
|
361
|
+
* @param flags 查询规则
|
|
362
|
+
*/
|
|
363
|
+
get(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
|
|
364
|
+
flags = flags || InjectFlags.Default;
|
|
365
|
+
if (flags === InjectFlags.SkipSelf) {
|
|
366
|
+
if (this.parentInjector) return this.parentInjector.get(token, notFoundValue);
|
|
367
|
+
if (notFoundValue !== THROW_IF_NOT_FOUND) return notFoundValue;
|
|
368
|
+
throw reflectiveInjectorErrorFn(token);
|
|
369
|
+
}
|
|
370
|
+
if (this.recordValues.has(token)) return this.recordValues.get(token);
|
|
371
|
+
for (let i = 0; i < this.normalizedProviders.length; i++) {
|
|
372
|
+
const normalizedProvider = this.normalizedProviders[i];
|
|
373
|
+
if (normalizedProvider.provide === token) return this.getValue(token, normalizedProvider);
|
|
374
|
+
}
|
|
375
|
+
if (!(token instanceof InjectionToken)) {
|
|
376
|
+
const scope = getAnnotations(token).getClassMetadata(Injectable)?.metadata.provideIn;
|
|
377
|
+
if (scope) {
|
|
378
|
+
const normalizedProvider = normalizeProvider(token);
|
|
379
|
+
if (this.scope === scope) {
|
|
380
|
+
this.normalizedProviders.push(normalizedProvider);
|
|
381
|
+
return this.getValue(token, normalizedProvider);
|
|
382
|
+
}
|
|
383
|
+
const parentInjector = this.parentInjector;
|
|
384
|
+
if (!parentInjector || parentInjector instanceof NullInjector) {
|
|
385
|
+
if (normalizedProvider.scope === "root") {
|
|
386
|
+
this.normalizedProviders.push(normalizedProvider);
|
|
387
|
+
return this.getValue(token, normalizedProvider);
|
|
388
|
+
}
|
|
389
|
+
if (notFoundValue !== THROW_IF_NOT_FOUND) return notFoundValue;
|
|
390
|
+
throw provideScopeError(normalizedProvider.scope);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (flags === InjectFlags.Self) {
|
|
395
|
+
if (notFoundValue === THROW_IF_NOT_FOUND) throw reflectiveInjectorErrorFn(token);
|
|
396
|
+
return notFoundValue;
|
|
397
|
+
}
|
|
398
|
+
if (this.parentInjector) return this.parentInjector.get(token, notFoundValue, flags === InjectFlags.Optional ? InjectFlags.Optional : InjectFlags.Default);
|
|
399
|
+
if (notFoundValue === THROW_IF_NOT_FOUND) throw reflectiveInjectorErrorFn(token);
|
|
400
|
+
return notFoundValue;
|
|
401
|
+
}
|
|
402
|
+
getValue(token, normalizedProvider) {
|
|
403
|
+
const { generateFactory, deps } = normalizedProvider;
|
|
404
|
+
const params = this.resolveDeps(deps);
|
|
405
|
+
let value = this.recordValues.get(token);
|
|
406
|
+
if (value) return value;
|
|
407
|
+
value = generateFactory(this, (token, value) => {
|
|
408
|
+
this.recordValues.set(token, value);
|
|
409
|
+
})(...params);
|
|
410
|
+
this.recordValues.set(token, value);
|
|
411
|
+
return value;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* 解决并获取依赖参数
|
|
415
|
+
* @param deps 依赖规则
|
|
416
|
+
* @private
|
|
417
|
+
*/
|
|
418
|
+
resolveDeps(deps) {
|
|
419
|
+
return deps.map((dep) => {
|
|
420
|
+
let reflectiveValue;
|
|
421
|
+
const tryValue = {};
|
|
422
|
+
const injectToken = dep.injectKey instanceof ForwardRef ? dep.injectKey.getRef() : dep.injectKey;
|
|
423
|
+
if (dep.visibility instanceof Self) reflectiveValue = this.get(injectToken, tryValue, InjectFlags.Self);
|
|
424
|
+
else if (dep.visibility instanceof SkipSelf) if (this.parentInjector) reflectiveValue = this.parentInjector.get(injectToken, tryValue);
|
|
425
|
+
else {
|
|
426
|
+
if (dep.optional) return null;
|
|
427
|
+
throw reflectiveInjectorErrorFn(injectToken);
|
|
428
|
+
}
|
|
429
|
+
else reflectiveValue = this.get(injectToken, tryValue);
|
|
430
|
+
if (reflectiveValue === tryValue) {
|
|
431
|
+
if (dep.optional) return null;
|
|
432
|
+
throw reflectiveInjectorErrorFn(injectToken);
|
|
433
|
+
}
|
|
434
|
+
return reflectiveValue;
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/di/type.ts
|
|
440
|
+
var Type = Function;
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/base/lifecycle.ts
|
|
443
|
+
/**
|
|
444
|
+
* 当组件挂载后调用回调函数
|
|
445
|
+
* @param callback 回调函数
|
|
446
|
+
* @returns 一个函数,用于停止监听
|
|
447
|
+
* @example
|
|
448
|
+
* ```tsx
|
|
449
|
+
* function App() {
|
|
450
|
+
* onMounted(() => {
|
|
451
|
+
* console.log('App mounted!')
|
|
452
|
+
* return () => {
|
|
453
|
+
* console.log('destroy prev mount!')
|
|
454
|
+
* }
|
|
455
|
+
* })
|
|
456
|
+
* return () => <div>...</div>
|
|
457
|
+
* }
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
function onMounted(callback) {
|
|
461
|
+
const component = getSetupContext();
|
|
462
|
+
if (!component.mountCallbacks) component.mountCallbacks = [];
|
|
463
|
+
component.mountCallbacks.push(callback);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* 当组件视图更新后调用回调函数
|
|
467
|
+
* @param callback 回调函数
|
|
468
|
+
* @returns 一个函数,用于停止监听
|
|
469
|
+
* @example
|
|
470
|
+
* ```tsx
|
|
471
|
+
* function App() {
|
|
472
|
+
* onUpdated(() => {
|
|
473
|
+
* console.log('App updated!')
|
|
474
|
+
* return () => {
|
|
475
|
+
* console.log('destroy prev update!')
|
|
476
|
+
* }
|
|
477
|
+
* })
|
|
478
|
+
* return () => <div>...</div>
|
|
479
|
+
* }
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
function onUpdated(callback) {
|
|
483
|
+
const component = getSetupContext();
|
|
484
|
+
if (!component.updatedCallbacks) component.updatedCallbacks = [];
|
|
485
|
+
component.updatedCallbacks.push(callback);
|
|
486
|
+
return () => {
|
|
487
|
+
const index = component.updatedCallbacks.indexOf(callback);
|
|
488
|
+
if (index > -1) component.updatedCallbacks.splice(index, 1);
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* 当组件销毁后调用回调函数
|
|
493
|
+
* @param callback 回调函数
|
|
494
|
+
* @returns 一个函数,用于停止监听
|
|
495
|
+
* @example
|
|
496
|
+
* ```tsx
|
|
497
|
+
* function App() {
|
|
498
|
+
* onUnmounted(() => {
|
|
499
|
+
* console.log('App unmounted!')
|
|
500
|
+
* })
|
|
501
|
+
* return () => <div>...</div>
|
|
502
|
+
* }
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
505
|
+
function onUnmounted(callback) {
|
|
506
|
+
const component = getSetupContext();
|
|
507
|
+
if (!component.unmountedCallbacks) component.unmountedCallbacks = [];
|
|
508
|
+
component.unmountedCallbacks.push(callback);
|
|
509
|
+
}
|
|
510
|
+
//#endregion
|
|
511
|
+
//#region src/reactive/_help.ts
|
|
512
|
+
var toStr = Object.prototype.toString;
|
|
513
|
+
function getStringType(v) {
|
|
514
|
+
return toStr.call(v);
|
|
515
|
+
}
|
|
516
|
+
function isArray(v) {
|
|
517
|
+
return Array.isArray(v);
|
|
518
|
+
}
|
|
519
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
520
|
+
function hasOwn(target, key) {
|
|
521
|
+
return hasOwnProperty.call(target, key);
|
|
522
|
+
}
|
|
523
|
+
//#endregion
|
|
524
|
+
//#region src/base/dep.ts
|
|
525
|
+
var Dep = class {
|
|
526
|
+
destroyCallbacks = [];
|
|
527
|
+
constructor(effect) {
|
|
528
|
+
this.effect = effect;
|
|
529
|
+
}
|
|
530
|
+
destroy() {
|
|
531
|
+
this.destroyCallbacks.forEach((callback) => callback());
|
|
532
|
+
this.destroyCallbacks = [];
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
var deps = [];
|
|
536
|
+
function getDepContext() {
|
|
537
|
+
return deps.at(-1);
|
|
538
|
+
}
|
|
539
|
+
function pushDepContext(dep) {
|
|
540
|
+
deps.push(dep);
|
|
541
|
+
}
|
|
542
|
+
function popDepContext() {
|
|
543
|
+
deps.pop();
|
|
544
|
+
}
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region src/reactive/effect.ts
|
|
547
|
+
var subscribers = /* @__PURE__ */ new WeakMap();
|
|
548
|
+
function getSubscriber(target) {
|
|
549
|
+
let subscriber = subscribers.get(target);
|
|
550
|
+
if (!subscriber) {
|
|
551
|
+
subscriber = /* @__PURE__ */ new Map();
|
|
552
|
+
subscribers.set(target, subscriber);
|
|
553
|
+
}
|
|
554
|
+
return subscriber;
|
|
555
|
+
}
|
|
556
|
+
var TrackOpTypes = /* @__PURE__ */ function(TrackOpTypes) {
|
|
557
|
+
TrackOpTypes["Get"] = "Get";
|
|
558
|
+
TrackOpTypes["Has"] = "Has";
|
|
559
|
+
TrackOpTypes["Iterate"] = "Iterate";
|
|
560
|
+
return TrackOpTypes;
|
|
561
|
+
}({});
|
|
562
|
+
var TriggerOpTypes = /* @__PURE__ */ function(TriggerOpTypes) {
|
|
563
|
+
TriggerOpTypes["Set"] = "Set";
|
|
564
|
+
TriggerOpTypes["Add"] = "Add";
|
|
565
|
+
TriggerOpTypes["Delete"] = "Delete";
|
|
566
|
+
TriggerOpTypes["Clear"] = "Clear";
|
|
567
|
+
return TriggerOpTypes;
|
|
568
|
+
}({});
|
|
569
|
+
var unKnownKey = Symbol("unKnownKey");
|
|
570
|
+
function track(target, type, key = unKnownKey) {
|
|
571
|
+
const dep = getDepContext();
|
|
572
|
+
if (dep) {
|
|
573
|
+
const subscriber = getSubscriber(target);
|
|
574
|
+
let record = subscriber.get(type);
|
|
575
|
+
if (!record) {
|
|
576
|
+
record = /* @__PURE__ */ new Map();
|
|
577
|
+
subscriber.set(type, record);
|
|
578
|
+
}
|
|
579
|
+
let effects = record.get(key);
|
|
580
|
+
if (!effects) {
|
|
581
|
+
effects = new Set([dep]);
|
|
582
|
+
record.set(key, effects);
|
|
583
|
+
dep.destroyCallbacks.push(() => {
|
|
584
|
+
effects.delete(dep);
|
|
585
|
+
});
|
|
586
|
+
} else if (!effects.has(dep)) {
|
|
587
|
+
dep.destroyCallbacks.push(() => {
|
|
588
|
+
effects.delete(dep);
|
|
589
|
+
});
|
|
590
|
+
effects.add(dep);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function runEffect(key, record) {
|
|
595
|
+
if (!record) return;
|
|
596
|
+
const effects = record.get(key);
|
|
597
|
+
if (effects) [...effects].forEach((i) => i.effect());
|
|
598
|
+
}
|
|
599
|
+
function trigger(target, type, key = unKnownKey) {
|
|
600
|
+
const subscriber = getSubscriber(target);
|
|
601
|
+
if (subscriber) switch (type) {
|
|
602
|
+
case TriggerOpTypes.Set:
|
|
603
|
+
if (isArray(target)) runEffect(unKnownKey, subscriber.get(TrackOpTypes.Iterate));
|
|
604
|
+
runEffect(key, subscriber.get(TrackOpTypes.Get));
|
|
605
|
+
runEffect(key, subscriber.get(TrackOpTypes.Has));
|
|
606
|
+
break;
|
|
607
|
+
case TriggerOpTypes.Add:
|
|
608
|
+
case TriggerOpTypes.Clear:
|
|
609
|
+
case TriggerOpTypes.Delete:
|
|
610
|
+
runEffect(unKnownKey, subscriber.get(TrackOpTypes.Iterate));
|
|
611
|
+
runEffect(key, subscriber.get(TrackOpTypes.Has));
|
|
612
|
+
runEffect(key, subscriber.get(TrackOpTypes.Get));
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region src/reactive/iterable-iterator.ts
|
|
618
|
+
function createIterableIterator(wrapper) {
|
|
619
|
+
return {
|
|
620
|
+
*entries() {
|
|
621
|
+
const target = toRaw(this);
|
|
622
|
+
track(target, TrackOpTypes.Iterate);
|
|
623
|
+
for (const [key, value] of target.entries()) yield [wrapper(key), wrapper(value)];
|
|
624
|
+
},
|
|
625
|
+
*keys() {
|
|
626
|
+
const target = toRaw(this);
|
|
627
|
+
track(target, TrackOpTypes.Iterate);
|
|
628
|
+
for (const item of target.keys()) yield wrapper(item);
|
|
629
|
+
},
|
|
630
|
+
*values() {
|
|
631
|
+
const target = toRaw(this);
|
|
632
|
+
track(target, TrackOpTypes.Iterate);
|
|
633
|
+
for (const item of target.values()) yield wrapper(item);
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/reactive/array-handlers.ts
|
|
639
|
+
function applyPredicateMethod(self, methodName, predicate, wrapper, thisArg) {
|
|
640
|
+
const target = toRaw(self);
|
|
641
|
+
track(target, TrackOpTypes.Iterate);
|
|
642
|
+
return target[methodName]((value, index, array) => {
|
|
643
|
+
return predicate.call(target, wrapper(value), index, array);
|
|
644
|
+
}, thisArg);
|
|
645
|
+
}
|
|
646
|
+
function applySearchMethod(self, methodName, args) {
|
|
647
|
+
const target = toRaw(self);
|
|
648
|
+
track(target, TrackOpTypes.Iterate);
|
|
649
|
+
return target[methodName](...args.map(toRaw));
|
|
650
|
+
}
|
|
651
|
+
function createArrayHandlers(wrapper) {
|
|
652
|
+
return {
|
|
653
|
+
concat(...items) {
|
|
654
|
+
const target = toRaw(this);
|
|
655
|
+
trigger(target, TriggerOpTypes.Add);
|
|
656
|
+
return target.concat(...items);
|
|
657
|
+
},
|
|
658
|
+
every(predicate, thisArg) {
|
|
659
|
+
return applyPredicateMethod(this, "every", predicate, wrapper, thisArg);
|
|
660
|
+
},
|
|
661
|
+
filter(predicate, thisArg) {
|
|
662
|
+
return applyPredicateMethod(this, "filter", predicate, wrapper, thisArg);
|
|
663
|
+
},
|
|
664
|
+
find(predicate, thisArg) {
|
|
665
|
+
return applyPredicateMethod(this, "find", predicate, wrapper, thisArg);
|
|
666
|
+
},
|
|
667
|
+
findIndex(predicate, thisArg) {
|
|
668
|
+
return applyPredicateMethod(this, "findIndex", predicate, wrapper, thisArg);
|
|
669
|
+
},
|
|
670
|
+
findLast(predicate, thisArg) {
|
|
671
|
+
return applyPredicateMethod(this, "findLast", predicate, wrapper, thisArg);
|
|
672
|
+
},
|
|
673
|
+
findLastIndex(predicate, thisArg) {
|
|
674
|
+
return applyPredicateMethod(this, "findLastIndex", predicate, wrapper, thisArg);
|
|
675
|
+
},
|
|
676
|
+
forEach(callbackfn, thisArg) {
|
|
677
|
+
return applyPredicateMethod(this, "forEach", callbackfn, wrapper, thisArg);
|
|
678
|
+
},
|
|
679
|
+
includes(...args) {
|
|
680
|
+
return applySearchMethod(this, "includes", args);
|
|
681
|
+
},
|
|
682
|
+
indexOf(...args) {
|
|
683
|
+
return applySearchMethod(this, "indexOf", args);
|
|
684
|
+
},
|
|
685
|
+
join(separator) {
|
|
686
|
+
const target = toRaw(this);
|
|
687
|
+
track(target, TrackOpTypes.Iterate);
|
|
688
|
+
return target.join(separator);
|
|
689
|
+
},
|
|
690
|
+
lastIndexOf(...args) {
|
|
691
|
+
return applySearchMethod(this, "lastIndexOf", args);
|
|
692
|
+
},
|
|
693
|
+
map(callbackFn, thisArg) {
|
|
694
|
+
return applyPredicateMethod(this, "map", callbackFn, wrapper, thisArg);
|
|
695
|
+
},
|
|
696
|
+
pop() {
|
|
697
|
+
const target = toRaw(this);
|
|
698
|
+
trigger(target, TriggerOpTypes.Delete);
|
|
699
|
+
return target.pop();
|
|
700
|
+
},
|
|
701
|
+
push(...items) {
|
|
702
|
+
const target = toRaw(this);
|
|
703
|
+
trigger(target, TriggerOpTypes.Add);
|
|
704
|
+
return target.push(...items);
|
|
705
|
+
},
|
|
706
|
+
reduce(callbackFn, ...args) {
|
|
707
|
+
const target = toRaw(this);
|
|
708
|
+
track(target, TrackOpTypes.Iterate);
|
|
709
|
+
return target.reduce((p, c, i, a) => {
|
|
710
|
+
if (args.length > 0) return callbackFn(p, wrapper(c), i, a);
|
|
711
|
+
return callbackFn(wrapper(p), wrapper(c), i, a);
|
|
712
|
+
}, ...args);
|
|
713
|
+
},
|
|
714
|
+
reduceRight(callbackFn, ...args) {
|
|
715
|
+
const target = toRaw(this);
|
|
716
|
+
track(target, TrackOpTypes.Iterate);
|
|
717
|
+
return target.reduceRight((p, c, i, a) => {
|
|
718
|
+
if (args.length > 0) return callbackFn(p, wrapper(c), i, a);
|
|
719
|
+
return callbackFn(wrapper(p), wrapper(c), i, a);
|
|
720
|
+
}, ...args);
|
|
721
|
+
},
|
|
722
|
+
shift() {
|
|
723
|
+
const target = toRaw(this);
|
|
724
|
+
trigger(target, TriggerOpTypes.Delete);
|
|
725
|
+
return target.shift();
|
|
726
|
+
},
|
|
727
|
+
some(predicate, thisArg) {
|
|
728
|
+
return applyPredicateMethod(this, "some", predicate, wrapper, thisArg);
|
|
729
|
+
},
|
|
730
|
+
splice(start, deleteCount) {
|
|
731
|
+
const target = toRaw(this);
|
|
732
|
+
trigger(target, TriggerOpTypes.Set);
|
|
733
|
+
trigger(target, TriggerOpTypes.Add);
|
|
734
|
+
trigger(target, TriggerOpTypes.Delete);
|
|
735
|
+
return target.splice(start, deleteCount).map((i) => wrapper(i));
|
|
736
|
+
},
|
|
737
|
+
toReversed() {
|
|
738
|
+
const target = toRaw(this);
|
|
739
|
+
track(target, TrackOpTypes.Iterate);
|
|
740
|
+
return target.toReversed();
|
|
741
|
+
},
|
|
742
|
+
toSorted(compareFn) {
|
|
743
|
+
const target = toRaw(this);
|
|
744
|
+
track(target, TrackOpTypes.Iterate);
|
|
745
|
+
return target.toSorted(compareFn);
|
|
746
|
+
},
|
|
747
|
+
toSpliced(start, deleteCount, ...items) {
|
|
748
|
+
const target = toRaw(this);
|
|
749
|
+
track(target, TrackOpTypes.Iterate);
|
|
750
|
+
return target.toSpliced(start, deleteCount, ...items);
|
|
751
|
+
},
|
|
752
|
+
unshift(...items) {
|
|
753
|
+
const target = toRaw(this);
|
|
754
|
+
trigger(target, TriggerOpTypes.Add);
|
|
755
|
+
return target.unshift(...items);
|
|
756
|
+
},
|
|
757
|
+
[Symbol.iterator]() {
|
|
758
|
+
return this.values();
|
|
759
|
+
},
|
|
760
|
+
...createIterableIterator(wrapper)
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
//#endregion
|
|
764
|
+
//#region src/reactive/map-handlers.ts
|
|
765
|
+
function createMapHandlers(wrapper) {
|
|
766
|
+
return {
|
|
767
|
+
get(key) {
|
|
768
|
+
const target = toRaw(this);
|
|
769
|
+
track(target, TrackOpTypes.Get, key);
|
|
770
|
+
return wrapper(target.get(key));
|
|
771
|
+
},
|
|
772
|
+
set(key, value) {
|
|
773
|
+
const target = toRaw(this);
|
|
774
|
+
key = toRaw(key);
|
|
775
|
+
value = toRaw(value);
|
|
776
|
+
const has = target.has(key);
|
|
777
|
+
const r = target.set(key, value);
|
|
778
|
+
trigger(target, has ? TriggerOpTypes.Set : TriggerOpTypes.Add, key);
|
|
779
|
+
return r;
|
|
780
|
+
},
|
|
781
|
+
has(key) {
|
|
782
|
+
const target = toRaw(this);
|
|
783
|
+
key = toRaw(key);
|
|
784
|
+
track(target, TrackOpTypes.Has, key);
|
|
785
|
+
return target.has(key);
|
|
786
|
+
},
|
|
787
|
+
delete(key) {
|
|
788
|
+
const target = toRaw(this);
|
|
789
|
+
key = toRaw(key);
|
|
790
|
+
const r = target.delete(key);
|
|
791
|
+
trigger(target, TriggerOpTypes.Delete, key);
|
|
792
|
+
return r;
|
|
793
|
+
},
|
|
794
|
+
forEach(callbackFn, thisArg) {
|
|
795
|
+
const target = toRaw(this);
|
|
796
|
+
track(target, TrackOpTypes.Iterate, void 0);
|
|
797
|
+
target.forEach((v, k, m) => {
|
|
798
|
+
callbackFn.call(this, wrapper(v), wrapper(k), m);
|
|
799
|
+
}, thisArg);
|
|
800
|
+
},
|
|
801
|
+
clear() {
|
|
802
|
+
const target = toRaw(this);
|
|
803
|
+
target.clear();
|
|
804
|
+
trigger(target, TriggerOpTypes.Clear, void 0);
|
|
805
|
+
},
|
|
806
|
+
[Symbol.iterator]() {
|
|
807
|
+
return this.entries();
|
|
808
|
+
},
|
|
809
|
+
...createIterableIterator(wrapper)
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
//#endregion
|
|
813
|
+
//#region src/reactive/set-handlers.ts
|
|
814
|
+
function createSetHandlers(wrapper) {
|
|
815
|
+
return {
|
|
816
|
+
add(value) {
|
|
817
|
+
const target = toRaw(this);
|
|
818
|
+
value = toRaw(value);
|
|
819
|
+
if (!target.has(value)) {
|
|
820
|
+
target.add(value);
|
|
821
|
+
trigger(target, TriggerOpTypes.Add, void 0);
|
|
822
|
+
}
|
|
823
|
+
return this;
|
|
824
|
+
},
|
|
825
|
+
delete(value) {
|
|
826
|
+
const target = toRaw(this);
|
|
827
|
+
value = toRaw(value);
|
|
828
|
+
const has = target.has(value);
|
|
829
|
+
const b = target.delete(value);
|
|
830
|
+
if (!has) trigger(target, TriggerOpTypes.Delete, void 0);
|
|
831
|
+
return b;
|
|
832
|
+
},
|
|
833
|
+
has(key) {
|
|
834
|
+
const target = toRaw(this);
|
|
835
|
+
key = toRaw(key);
|
|
836
|
+
track(target, TrackOpTypes.Has, key);
|
|
837
|
+
return target.has(key);
|
|
838
|
+
},
|
|
839
|
+
forEach(callbackFn, thisArg) {
|
|
840
|
+
const target = toRaw(this);
|
|
841
|
+
track(target, TrackOpTypes.Iterate, void 0);
|
|
842
|
+
target.forEach((v, k, m) => {
|
|
843
|
+
callbackFn.call(this, wrapper(v), wrapper(k), m);
|
|
844
|
+
}, thisArg);
|
|
845
|
+
},
|
|
846
|
+
clear() {
|
|
847
|
+
const target = toRaw(this);
|
|
848
|
+
if (target.size !== 0) {
|
|
849
|
+
target.clear();
|
|
850
|
+
trigger(target, TriggerOpTypes.Clear, void 0);
|
|
851
|
+
}
|
|
852
|
+
},
|
|
853
|
+
[Symbol.iterator]() {
|
|
854
|
+
return this.values();
|
|
855
|
+
},
|
|
856
|
+
...createIterableIterator(wrapper)
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
//#endregion
|
|
860
|
+
//#region src/reactive/reactive.ts
|
|
861
|
+
var reactiveErrorFn = makeError("reactive");
|
|
862
|
+
var rawToProxyCache = /* @__PURE__ */ new WeakMap();
|
|
863
|
+
var proxyToRawCache = /* @__PURE__ */ new WeakMap();
|
|
864
|
+
/**
|
|
865
|
+
* 将响应式对象转换为原始对象
|
|
866
|
+
* @param value 响应式对象
|
|
867
|
+
* @returns 原始对象
|
|
868
|
+
* @example
|
|
869
|
+
* ```tsx
|
|
870
|
+
* const obj = reactive({
|
|
871
|
+
* name: 'John',
|
|
872
|
+
* age: 18
|
|
873
|
+
* })
|
|
874
|
+
* console.log(toRaw(obj))
|
|
875
|
+
* ```
|
|
876
|
+
*/
|
|
877
|
+
function toRaw(value) {
|
|
878
|
+
if (proxyToRawCache.has(value)) return proxyToRawCache.get(value);
|
|
879
|
+
return value;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* 检查对象是否是响应式对象
|
|
883
|
+
* @param value 要检查的对象
|
|
884
|
+
* @returns 是否是响应式对象
|
|
885
|
+
* @example
|
|
886
|
+
* ```tsx
|
|
887
|
+
* const obj = reactive({
|
|
888
|
+
* name: 'John',
|
|
889
|
+
* age: 18
|
|
890
|
+
* })
|
|
891
|
+
* console.log(isReactive(obj))
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
894
|
+
function isReactive(value) {
|
|
895
|
+
return proxyToRawCache.has(value);
|
|
896
|
+
}
|
|
897
|
+
var fromInternalWrite = false;
|
|
898
|
+
/**
|
|
899
|
+
* 内部写入,用于避免类型为只读的响应式对象写入报错
|
|
900
|
+
* @param fn 要执行的函数
|
|
901
|
+
* @internal
|
|
902
|
+
*/
|
|
903
|
+
function internalWrite(fn) {
|
|
904
|
+
fromInternalWrite = true;
|
|
905
|
+
fn();
|
|
906
|
+
fromInternalWrite = false;
|
|
907
|
+
}
|
|
908
|
+
var ObjectReactiveHandler = class {
|
|
909
|
+
isShallow;
|
|
910
|
+
isReadonly;
|
|
911
|
+
constructor(config) {
|
|
912
|
+
this.isReadonly = config.readonly;
|
|
913
|
+
this.isShallow = config.shallow;
|
|
914
|
+
}
|
|
915
|
+
set(target, p, newValue, receiver) {
|
|
916
|
+
if (this.isReadonly && !fromInternalWrite) throw reactiveErrorFn("Object is readonly!");
|
|
917
|
+
const rawValue = toRaw(newValue);
|
|
918
|
+
const oldValue = target[p];
|
|
919
|
+
const v = this.isShallow ? newValue : rawValue;
|
|
920
|
+
if (oldValue === rawValue) return Reflect.set(target, p, v, receiver);
|
|
921
|
+
const b = Reflect.set(target, p, v, receiver);
|
|
922
|
+
fromInternalWrite = false;
|
|
923
|
+
if (hasOwn(target, p)) trigger(target, TriggerOpTypes.Set, p);
|
|
924
|
+
else trigger(target, TriggerOpTypes.Add, p);
|
|
925
|
+
return b;
|
|
926
|
+
}
|
|
927
|
+
get(target, p, receiver) {
|
|
928
|
+
track(target, TrackOpTypes.Get, p);
|
|
929
|
+
const value = Reflect.get(target, p, receiver);
|
|
930
|
+
if (this.isShallow) return value;
|
|
931
|
+
return reactive(value);
|
|
932
|
+
}
|
|
933
|
+
deleteProperty(target, p) {
|
|
934
|
+
const b = Reflect.deleteProperty(target, p);
|
|
935
|
+
trigger(target, TriggerOpTypes.Delete, p);
|
|
936
|
+
return b;
|
|
937
|
+
}
|
|
938
|
+
ownKeys(target) {
|
|
939
|
+
track(target, TrackOpTypes.Iterate);
|
|
940
|
+
return Reflect.ownKeys(target);
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
function noReactive(v) {
|
|
944
|
+
return v;
|
|
945
|
+
}
|
|
946
|
+
var ArrayReactiveHandler = class extends ObjectReactiveHandler {
|
|
947
|
+
interceptors = createArrayHandlers(this.isShallow ? noReactive : reactive);
|
|
948
|
+
constructor(config) {
|
|
949
|
+
super(config);
|
|
950
|
+
}
|
|
951
|
+
get(target, p, receiver) {
|
|
952
|
+
if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
|
|
953
|
+
return super.get(target, p, receiver);
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
var MapReactiveHandler = class extends ObjectReactiveHandler {
|
|
957
|
+
interceptors = createMapHandlers(this.isShallow ? noReactive : reactive);
|
|
958
|
+
constructor(config) {
|
|
959
|
+
super(config);
|
|
960
|
+
}
|
|
961
|
+
get(target, p, receiver) {
|
|
962
|
+
if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
|
|
963
|
+
if (p === "size") {
|
|
964
|
+
track(target, TrackOpTypes.Iterate, p);
|
|
965
|
+
return Reflect.get(target, p);
|
|
966
|
+
}
|
|
967
|
+
return super.get(target, p, receiver);
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
var SetReactiveHandler = class extends ObjectReactiveHandler {
|
|
971
|
+
interceptors = createSetHandlers(this.isShallow ? noReactive : reactive);
|
|
972
|
+
constructor(config) {
|
|
973
|
+
super(config);
|
|
974
|
+
}
|
|
975
|
+
get(target, p, receiver) {
|
|
976
|
+
if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
|
|
977
|
+
if (p === "size") {
|
|
978
|
+
track(target, TrackOpTypes.Iterate, p);
|
|
979
|
+
return Reflect.get(target, p);
|
|
980
|
+
}
|
|
981
|
+
return super.get(target, p, receiver);
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
var defaultObjectReactiveHandler = new ObjectReactiveHandler({
|
|
985
|
+
readonly: false,
|
|
986
|
+
shallow: false
|
|
987
|
+
});
|
|
988
|
+
var defaultArrayReactiveHandler = new ArrayReactiveHandler({
|
|
989
|
+
readonly: false,
|
|
990
|
+
shallow: false
|
|
991
|
+
});
|
|
992
|
+
var defaultMapReactiveHandler = new MapReactiveHandler({
|
|
993
|
+
readonly: false,
|
|
994
|
+
shallow: false
|
|
995
|
+
});
|
|
996
|
+
var defaultSetReactiveHandler = new SetReactiveHandler({
|
|
997
|
+
readonly: false,
|
|
998
|
+
shallow: false
|
|
999
|
+
});
|
|
1000
|
+
var readonlyProxyHandler = new ObjectReactiveHandler({
|
|
1001
|
+
shallow: true,
|
|
1002
|
+
readonly: true
|
|
1003
|
+
});
|
|
1004
|
+
function createShallowReadonlyProxy(value) {
|
|
1005
|
+
return new Proxy(value, readonlyProxyHandler);
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* 创建一个响应式对象
|
|
1009
|
+
* @param raw 原始对象
|
|
1010
|
+
* @returns 响应式对象
|
|
1011
|
+
* @example
|
|
1012
|
+
* ```tsx
|
|
1013
|
+
* const obj = reactive({
|
|
1014
|
+
* name: 'John',
|
|
1015
|
+
* age: 18,
|
|
1016
|
+
* children: [
|
|
1017
|
+
* {
|
|
1018
|
+
* name: 'Jane',
|
|
1019
|
+
* age: 16
|
|
1020
|
+
* }
|
|
1021
|
+
* ]
|
|
1022
|
+
* })
|
|
1023
|
+
* console.log(obj.name)
|
|
1024
|
+
* console.log(obj.children[0].name)
|
|
1025
|
+
* ```
|
|
1026
|
+
*/
|
|
1027
|
+
function reactive(raw) {
|
|
1028
|
+
if (isReactive(raw)) return raw;
|
|
1029
|
+
let proxy = rawToProxyCache.get(raw);
|
|
1030
|
+
if (proxy) return proxy;
|
|
1031
|
+
switch (getStringType(raw)) {
|
|
1032
|
+
case "[object Object]":
|
|
1033
|
+
proxy = new Proxy(raw, defaultObjectReactiveHandler);
|
|
1034
|
+
break;
|
|
1035
|
+
case "[object Array]":
|
|
1036
|
+
proxy = new Proxy(raw, defaultArrayReactiveHandler);
|
|
1037
|
+
break;
|
|
1038
|
+
case "[object Set]":
|
|
1039
|
+
case "[object WeakSet]":
|
|
1040
|
+
proxy = new Proxy(raw, defaultSetReactiveHandler);
|
|
1041
|
+
break;
|
|
1042
|
+
case "[object Map]":
|
|
1043
|
+
case "[object WeakMap]":
|
|
1044
|
+
proxy = new Proxy(raw, defaultMapReactiveHandler);
|
|
1045
|
+
break;
|
|
1046
|
+
default: return raw;
|
|
1047
|
+
}
|
|
1048
|
+
rawToProxyCache.set(raw, proxy);
|
|
1049
|
+
proxyToRawCache.set(proxy, raw);
|
|
1050
|
+
return proxy;
|
|
1051
|
+
}
|
|
1052
|
+
//#endregion
|
|
1053
|
+
//#region src/base/_utils.ts
|
|
1054
|
+
function hasChange(newProps, oldProps) {
|
|
1055
|
+
const newKeys = Object.keys(oldProps);
|
|
1056
|
+
const oldKeys = Object.keys(newProps);
|
|
1057
|
+
if (oldKeys.length !== newKeys.length) return true;
|
|
1058
|
+
const len = oldKeys.length;
|
|
1059
|
+
for (let i = 0; i < len; i++) {
|
|
1060
|
+
const key = newKeys[i];
|
|
1061
|
+
if (newProps[key] !== oldProps[key]) return true;
|
|
1062
|
+
}
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
|
|
1066
|
+
for (const key in oldProps) if (!(key in newProps)) onDeleted(key, oldProps[key]);
|
|
1067
|
+
for (const key in newProps) if (!(key in oldProps)) onAdded(key, newProps[key]);
|
|
1068
|
+
else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
|
|
1069
|
+
}
|
|
1070
|
+
function classToString(config) {
|
|
1071
|
+
if (typeof config === "string") return config;
|
|
1072
|
+
if (!config) return "";
|
|
1073
|
+
if (Array.isArray(config)) {
|
|
1074
|
+
const classes = [];
|
|
1075
|
+
for (const i of config) {
|
|
1076
|
+
const v = classToString(i);
|
|
1077
|
+
if (v) classes.push(v);
|
|
1078
|
+
}
|
|
1079
|
+
return classes.join(" ");
|
|
1080
|
+
}
|
|
1081
|
+
if (typeof config === "object") {
|
|
1082
|
+
if (config.toString !== Object.prototype.toString && !config.toString.toString().includes("[native code]")) return config.toString();
|
|
1083
|
+
const classes = [];
|
|
1084
|
+
for (const key in config) if ({}.hasOwnProperty.call(config, key) && config[key]) classes.push(key);
|
|
1085
|
+
return classes.join(" ");
|
|
1086
|
+
}
|
|
1087
|
+
return "";
|
|
1088
|
+
}
|
|
1089
|
+
function styleToObject(style) {
|
|
1090
|
+
if (typeof style !== "string") return style || {};
|
|
1091
|
+
const obj = {};
|
|
1092
|
+
style.split(";").map((s) => s.split(":")).forEach((v) => {
|
|
1093
|
+
if (!v[0] || !v[1]) return;
|
|
1094
|
+
obj[v[0].trim()] = v[1].trim();
|
|
1095
|
+
});
|
|
1096
|
+
return obj;
|
|
1097
|
+
}
|
|
1098
|
+
var TextAtomType = Symbol("Text");
|
|
1099
|
+
var ElementAtomType = Symbol("Element");
|
|
1100
|
+
var ComponentAtomType = Symbol("Component");
|
|
1101
|
+
//#endregion
|
|
1102
|
+
//#region src/base/ref.ts
|
|
1103
|
+
var refErrorFn = makeError("Ref");
|
|
1104
|
+
/**
|
|
1105
|
+
* 创建一个动态 ref,当 ref 的绑定的元素或组件初始化后,会调用副作用函数,并把元素或组件的实例作为参数传入。
|
|
1106
|
+
* @param effect 用于接收实例的副作用函数,该函数还可以返回一个清理副作用的函数,当元素或组件销毁时调用
|
|
1107
|
+
* @returns 一个函数,用于清理副作用
|
|
1108
|
+
* @example
|
|
1109
|
+
* ```tsx
|
|
1110
|
+
* function App() {
|
|
1111
|
+
* const ref = createDynamicRef<HTMLDivElement>((node) => {
|
|
1112
|
+
* console.log(node)
|
|
1113
|
+
* return () => {
|
|
1114
|
+
* console.log('destroy')
|
|
1115
|
+
* }
|
|
1116
|
+
* })
|
|
1117
|
+
* return () => {
|
|
1118
|
+
* return <div ref={ref}>test</div>
|
|
1119
|
+
* }
|
|
1120
|
+
* }
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
function createDynamicRef(effect) {
|
|
1124
|
+
return effect;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* 创建一个引用对象,并添加到 JSX 节点上属性上,当组件渲染后,即可通过 .value 获取到绑定节点的实例
|
|
1128
|
+
* - 当绑定到虚拟 DOM 元素节点上时,value 为当前节点的 DOM 元素
|
|
1129
|
+
* - 当绑定到组件节点上时,value 为组件函数返回的对象
|
|
1130
|
+
* @example
|
|
1131
|
+
* ```tsx
|
|
1132
|
+
* function App() {
|
|
1133
|
+
* const ref = createRef<HTMLDivElement>()
|
|
1134
|
+
* onMounted(() => {
|
|
1135
|
+
* console.log(ref.value)
|
|
1136
|
+
* })
|
|
1137
|
+
* return () => {
|
|
1138
|
+
* return <div ref={ref}>...</div>
|
|
1139
|
+
* }
|
|
1140
|
+
* }
|
|
1141
|
+
* ```
|
|
1142
|
+
*/
|
|
1143
|
+
function createRef() {
|
|
1144
|
+
return createShallowReadonlyProxy({ value: null });
|
|
1145
|
+
}
|
|
1146
|
+
function applyRefs(ref, value, refEffects) {
|
|
1147
|
+
if (!ref) return;
|
|
1148
|
+
const refs = toRefs(ref);
|
|
1149
|
+
const length = refs.length;
|
|
1150
|
+
for (let i = 0; i < length; i++) bindRefs(refs[i], value, refEffects);
|
|
1151
|
+
}
|
|
1152
|
+
function updateRefs(ref, value, refEffects) {
|
|
1153
|
+
if (!ref) {
|
|
1154
|
+
refEffects.forEach((fn, oldRef) => {
|
|
1155
|
+
refEffects.delete(oldRef);
|
|
1156
|
+
if (typeof fn === "function") fn();
|
|
1157
|
+
});
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
const newRefs = toRefs(ref);
|
|
1161
|
+
refEffects.forEach((fn, oldRef) => {
|
|
1162
|
+
if (newRefs.includes(oldRef)) return;
|
|
1163
|
+
refEffects.delete(oldRef);
|
|
1164
|
+
if (typeof fn === "function") fn();
|
|
1165
|
+
});
|
|
1166
|
+
const len = newRefs.length;
|
|
1167
|
+
for (let i = 0; i < len; i++) {
|
|
1168
|
+
const newRef = newRefs[i];
|
|
1169
|
+
if (refEffects.has(newRef)) continue;
|
|
1170
|
+
bindRefs(newRef, value, refEffects);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
function toRefs(ref) {
|
|
1174
|
+
return Array.isArray(ref) ? ref : [ref];
|
|
1175
|
+
}
|
|
1176
|
+
function bindRefs(ref, value, refEffects) {
|
|
1177
|
+
const type = typeof ref;
|
|
1178
|
+
if (type === "function") {
|
|
1179
|
+
const fn = ref(value);
|
|
1180
|
+
refEffects.set(ref, fn);
|
|
1181
|
+
} else if (type === "object") {
|
|
1182
|
+
internalWrite(() => {
|
|
1183
|
+
ref.value = value;
|
|
1184
|
+
});
|
|
1185
|
+
refEffects.set(ref, () => {
|
|
1186
|
+
internalWrite(() => {
|
|
1187
|
+
ref.value = null;
|
|
1188
|
+
});
|
|
1189
|
+
});
|
|
1190
|
+
} else throw refErrorFn("ref must be a function or `Ref<T>` object!");
|
|
1191
|
+
}
|
|
1192
|
+
//#endregion
|
|
1193
|
+
//#region src/base/component.ts
|
|
1194
|
+
var componentSetupStack = [];
|
|
1195
|
+
var componentErrorFn = makeError("component");
|
|
1196
|
+
function getSetupContext(need = true) {
|
|
1197
|
+
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
1198
|
+
if (!current && need) throw componentErrorFn("cannot be called outside the component!");
|
|
1199
|
+
return current;
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
1203
|
+
*/
|
|
1204
|
+
var Component = class {
|
|
1205
|
+
get dirty() {
|
|
1206
|
+
return this._dirty;
|
|
1207
|
+
}
|
|
1208
|
+
get changed() {
|
|
1209
|
+
return this._changed;
|
|
1210
|
+
}
|
|
1211
|
+
constructor(parentComponent, type, props, key) {
|
|
1212
|
+
this.parentComponent = parentComponent;
|
|
1213
|
+
this.type = type;
|
|
1214
|
+
this.props = props;
|
|
1215
|
+
this.key = key;
|
|
1216
|
+
this.instance = null;
|
|
1217
|
+
this.changedSubComponents = /* @__PURE__ */ new Set();
|
|
1218
|
+
this.viewMetadata = null;
|
|
1219
|
+
this.unmountedCallbacks = null;
|
|
1220
|
+
this.mountCallbacks = null;
|
|
1221
|
+
this.updatedCallbacks = null;
|
|
1222
|
+
this.updatedDestroyCallbacks = null;
|
|
1223
|
+
this._dirty = true;
|
|
1224
|
+
this._changed = false;
|
|
1225
|
+
this.isFirstRendering = true;
|
|
1226
|
+
this.rawProps = props;
|
|
1227
|
+
this.props = createShallowReadonlyProxy({ ...props });
|
|
1228
|
+
this.refEffects = /* @__PURE__ */ new Map();
|
|
1229
|
+
this.listener = new Dep(() => {
|
|
1230
|
+
this.markAsDirtied();
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
markAsDirtied() {
|
|
1234
|
+
this._dirty = true;
|
|
1235
|
+
this.markAsChanged();
|
|
1236
|
+
}
|
|
1237
|
+
markAsChanged(changedComponent) {
|
|
1238
|
+
if (changedComponent) this.changedSubComponents.add(changedComponent);
|
|
1239
|
+
if (this._changed) return;
|
|
1240
|
+
this._changed = true;
|
|
1241
|
+
if (this.parentComponent) this.parentComponent.markAsChanged(this);
|
|
1242
|
+
}
|
|
1243
|
+
render(update) {
|
|
1244
|
+
componentSetupStack.push(this);
|
|
1245
|
+
const render = this.type(this.props);
|
|
1246
|
+
const isRenderFn = typeof render === "function";
|
|
1247
|
+
this.instance = isRenderFn ? { $render: render } : render;
|
|
1248
|
+
onMounted(() => {
|
|
1249
|
+
applyRefs(this.props.ref, this.instance, this.refEffects);
|
|
1250
|
+
return () => {
|
|
1251
|
+
this.refEffects.forEach((fn) => {
|
|
1252
|
+
if (typeof fn === "function") fn();
|
|
1253
|
+
});
|
|
1254
|
+
};
|
|
1255
|
+
});
|
|
1256
|
+
componentSetupStack.pop();
|
|
1257
|
+
pushDepContext(this.listener);
|
|
1258
|
+
const template = this.instance.$render();
|
|
1259
|
+
popDepContext();
|
|
1260
|
+
update(template, this.instance.$portalHost);
|
|
1261
|
+
this.rendered();
|
|
1262
|
+
}
|
|
1263
|
+
updateProps(newProps) {
|
|
1264
|
+
const oldProps = this.rawProps;
|
|
1265
|
+
this.rawProps = newProps;
|
|
1266
|
+
const newRefs = newProps.ref;
|
|
1267
|
+
comparePropsWithCallbacks(oldProps, newProps, (key) => {
|
|
1268
|
+
internalWrite(() => {
|
|
1269
|
+
Reflect.deleteProperty(oldProps, key);
|
|
1270
|
+
});
|
|
1271
|
+
}, (key, value) => {
|
|
1272
|
+
internalWrite(() => {
|
|
1273
|
+
this.props[key] = value;
|
|
1274
|
+
});
|
|
1275
|
+
}, (key, value) => {
|
|
1276
|
+
internalWrite(() => {
|
|
1277
|
+
this.props[key] = value;
|
|
1278
|
+
});
|
|
1279
|
+
});
|
|
1280
|
+
updateRefs(newRefs, this.instance, this.refEffects);
|
|
1281
|
+
}
|
|
1282
|
+
rerender() {
|
|
1283
|
+
this.listener.destroy();
|
|
1284
|
+
pushDepContext(this.listener);
|
|
1285
|
+
const template = this.instance.$render();
|
|
1286
|
+
popDepContext();
|
|
1287
|
+
return template;
|
|
1288
|
+
}
|
|
1289
|
+
destroy() {
|
|
1290
|
+
this.listener.destroy();
|
|
1291
|
+
if (this.updatedDestroyCallbacks) this.updatedDestroyCallbacks.forEach((fn) => {
|
|
1292
|
+
fn();
|
|
1293
|
+
});
|
|
1294
|
+
if (this.unmountedCallbacks) this.unmountedCallbacks.forEach((fn) => {
|
|
1295
|
+
fn();
|
|
1296
|
+
});
|
|
1297
|
+
this.parentComponent = this.updatedDestroyCallbacks = this.mountCallbacks = this.updatedCallbacks = this.unmountedCallbacks = null;
|
|
1298
|
+
}
|
|
1299
|
+
rendered() {
|
|
1300
|
+
this.changedSubComponents.clear();
|
|
1301
|
+
const is = this.isFirstRendering;
|
|
1302
|
+
this.isFirstRendering = false;
|
|
1303
|
+
this._dirty = this._changed = false;
|
|
1304
|
+
this.invokeUpdatedHooks();
|
|
1305
|
+
if (is) this.invokeMountHooks();
|
|
1306
|
+
if (this.changed) Promise.resolve().then(() => {
|
|
1307
|
+
if (this.parentComponent) this.parentComponent.markAsChanged(this);
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
invokeMountHooks() {
|
|
1311
|
+
const unmountedCallbacks = [];
|
|
1312
|
+
if (this.mountCallbacks) {
|
|
1313
|
+
const len = this.mountCallbacks.length;
|
|
1314
|
+
for (let i = 0; i < len; ++i) {
|
|
1315
|
+
const fn = this.mountCallbacks[i];
|
|
1316
|
+
const destroyFn = fn();
|
|
1317
|
+
if (typeof destroyFn === "function") unmountedCallbacks.push(destroyFn);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (unmountedCallbacks.length) if (this.unmountedCallbacks) this.unmountedCallbacks.push(...unmountedCallbacks);
|
|
1321
|
+
else this.unmountedCallbacks = unmountedCallbacks;
|
|
1322
|
+
this.mountCallbacks = null;
|
|
1323
|
+
}
|
|
1324
|
+
invokeUpdatedHooks() {
|
|
1325
|
+
if (this.updatedCallbacks) {
|
|
1326
|
+
if (this.updatedDestroyCallbacks) this.updatedDestroyCallbacks.forEach((fn) => {
|
|
1327
|
+
fn();
|
|
1328
|
+
});
|
|
1329
|
+
const updatedDestroyCallbacks = [];
|
|
1330
|
+
const len = this.updatedCallbacks.length;
|
|
1331
|
+
for (let i = 0; i < len; ++i) {
|
|
1332
|
+
const fn = this.updatedCallbacks[i];
|
|
1333
|
+
const destroyFn = fn();
|
|
1334
|
+
if (typeof destroyFn === "function") updatedDestroyCallbacks.push(destroyFn);
|
|
1335
|
+
}
|
|
1336
|
+
this.updatedDestroyCallbacks = updatedDestroyCallbacks.length ? updatedDestroyCallbacks : null;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1340
|
+
/**
|
|
1341
|
+
* 获取当前组件实例
|
|
1342
|
+
* @returns 当前组件实例
|
|
1343
|
+
* @example
|
|
1344
|
+
* ```tsx
|
|
1345
|
+
* function App() {
|
|
1346
|
+
* const instance = getCurrentInstance()
|
|
1347
|
+
* console.log(instance)
|
|
1348
|
+
* return () => <div>...</div>
|
|
1349
|
+
* }
|
|
1350
|
+
* ```
|
|
1351
|
+
*/
|
|
1352
|
+
function getCurrentInstance() {
|
|
1353
|
+
return getSetupContext();
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* 注册组件销毁回调函数
|
|
1357
|
+
* @param fn 要注册的回调函数
|
|
1358
|
+
* @internal
|
|
1359
|
+
*/
|
|
1360
|
+
function registryComponentDestroyCallback(fn) {
|
|
1361
|
+
const component = getSetupContext(false);
|
|
1362
|
+
if (component) {
|
|
1363
|
+
if (!component.unmountedCallbacks) component.unmountedCallbacks = [];
|
|
1364
|
+
component.unmountedCallbacks.push(fn);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
//#endregion
|
|
1368
|
+
//#region src/base/jsx-element.ts
|
|
1369
|
+
function Fragment(props) {
|
|
1370
|
+
return () => {
|
|
1371
|
+
return props.children;
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
function jsx(type, props, key) {
|
|
1375
|
+
return JSXNodeFactory.createNode(type, props, key);
|
|
1376
|
+
}
|
|
1377
|
+
var jsxs = jsx;
|
|
1378
|
+
var JSXNodeFactory = { createNode(type, props, key) {
|
|
1379
|
+
return {
|
|
1380
|
+
type,
|
|
1381
|
+
props,
|
|
1382
|
+
key
|
|
1383
|
+
};
|
|
1384
|
+
} };
|
|
1385
|
+
/**
|
|
1386
|
+
* 给组件的视图元素节点添加自定义属性标记
|
|
1387
|
+
* @param marks
|
|
1388
|
+
* @param setup
|
|
1389
|
+
* @example
|
|
1390
|
+
* ```tsx
|
|
1391
|
+
* const App = withMark('mark', function(props) {
|
|
1392
|
+
* return () => {
|
|
1393
|
+
* return <div>...</div>
|
|
1394
|
+
* }
|
|
1395
|
+
* })
|
|
1396
|
+
* ```
|
|
1397
|
+
*/
|
|
1398
|
+
function withMark(marks, setup) {
|
|
1399
|
+
if (!marks) return setup;
|
|
1400
|
+
return function(props) {
|
|
1401
|
+
const componentRenderFn = setup(props);
|
|
1402
|
+
if (typeof componentRenderFn === "function") return function() {
|
|
1403
|
+
return applyMark(marks, componentRenderFn);
|
|
1404
|
+
};
|
|
1405
|
+
const oldRender = componentRenderFn.$render;
|
|
1406
|
+
componentRenderFn.$render = function() {
|
|
1407
|
+
return applyMark(marks, () => {
|
|
1408
|
+
return oldRender.call(componentRenderFn);
|
|
1409
|
+
});
|
|
1410
|
+
};
|
|
1411
|
+
return componentRenderFn;
|
|
1412
|
+
};
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* 内部使用
|
|
1416
|
+
* @internal
|
|
1417
|
+
* @param mark
|
|
1418
|
+
* @param render
|
|
1419
|
+
*/
|
|
1420
|
+
function applyMark(mark, render) {
|
|
1421
|
+
const oldCreateNote = JSXNodeFactory.createNode;
|
|
1422
|
+
const spaces = Array.isArray(mark) ? mark : [mark];
|
|
1423
|
+
JSXNodeFactory.createNode = function(name, props, key) {
|
|
1424
|
+
for (const scopedId of spaces) props[scopedId] = "";
|
|
1425
|
+
return oldCreateNote.apply(JSXNodeFactory, [
|
|
1426
|
+
name,
|
|
1427
|
+
props,
|
|
1428
|
+
key
|
|
1429
|
+
]);
|
|
1430
|
+
};
|
|
1431
|
+
const vDom = render();
|
|
1432
|
+
JSXNodeFactory.createNode = oldCreateNote;
|
|
1433
|
+
return vDom;
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* 将子节点渲染到指定节点
|
|
1437
|
+
* @param props
|
|
1438
|
+
* @example
|
|
1439
|
+
* ```tsx
|
|
1440
|
+
* function App() {
|
|
1441
|
+
* const modal = document.getElementById('modal')!
|
|
1442
|
+
* return () => {
|
|
1443
|
+
* return (
|
|
1444
|
+
* <div>
|
|
1445
|
+
* <Portal host={modal}>
|
|
1446
|
+
* 这里的内容将渲染到 modal 节点
|
|
1447
|
+
* </Portal>
|
|
1448
|
+
* </div>
|
|
1449
|
+
* )
|
|
1450
|
+
* }
|
|
1451
|
+
* }
|
|
1452
|
+
* ```
|
|
1453
|
+
*/
|
|
1454
|
+
function Portal(props) {
|
|
1455
|
+
return {
|
|
1456
|
+
$portalHost: props.host,
|
|
1457
|
+
$render() {
|
|
1458
|
+
return props.children;
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
//#endregion
|
|
1463
|
+
//#region src/reactive/watch-effect.ts
|
|
1464
|
+
/**
|
|
1465
|
+
* 创建一个 watchEffect,立即执行 effect 函数,当依赖的值发生变化时,会再次执行 effect 函数。
|
|
1466
|
+
* watchEffect 会返回一个函数,用于停止监听
|
|
1467
|
+
* @param effect 执行的函数
|
|
1468
|
+
* @returns 一个函数,用于停止监听
|
|
1469
|
+
*/
|
|
1470
|
+
function watchEffect(effect) {
|
|
1471
|
+
const dep = new Dep(function() {
|
|
1472
|
+
pushDepContext(dep);
|
|
1473
|
+
effect();
|
|
1474
|
+
popDepContext();
|
|
1475
|
+
});
|
|
1476
|
+
pushDepContext(dep);
|
|
1477
|
+
effect();
|
|
1478
|
+
popDepContext();
|
|
1479
|
+
function unWatch() {
|
|
1480
|
+
dep.destroy();
|
|
1481
|
+
}
|
|
1482
|
+
registryComponentDestroyCallback(unWatch);
|
|
1483
|
+
return unWatch;
|
|
1484
|
+
}
|
|
1485
|
+
//#endregion
|
|
1486
|
+
//#region src/reactive/watch.ts
|
|
1487
|
+
/**
|
|
1488
|
+
* 创建一个 watch,当依赖的值发生变化时,会执行 callback 函数。
|
|
1489
|
+
* watch 会返回一个函数,用于停止监听。
|
|
1490
|
+
* @param trigger 触发函数,用于获取依赖的值
|
|
1491
|
+
* @param callback 回调函数,当依赖的值发生变化时,会执行 callback 函数
|
|
1492
|
+
* @returns 一个函数,用于停止监听
|
|
1493
|
+
*/
|
|
1494
|
+
function watch(trigger, callback) {
|
|
1495
|
+
const initValue = {};
|
|
1496
|
+
let oldValue = initValue;
|
|
1497
|
+
const unWatch = watchEffect(function() {
|
|
1498
|
+
if (oldValue === initValue) {
|
|
1499
|
+
oldValue = trigger();
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
const newValue = trigger();
|
|
1503
|
+
if (newValue !== oldValue) {
|
|
1504
|
+
callback(newValue, oldValue);
|
|
1505
|
+
oldValue = newValue;
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
registryComponentDestroyCallback(unWatch);
|
|
1509
|
+
return unWatch;
|
|
1510
|
+
}
|
|
1511
|
+
//#endregion
|
|
1512
|
+
//#region src/base/context.ts
|
|
1513
|
+
var injectMap = /* @__PURE__ */ new WeakMap();
|
|
1514
|
+
function getInjector(start) {
|
|
1515
|
+
while (start) {
|
|
1516
|
+
const injector = injectMap.get(start);
|
|
1517
|
+
if (injector) return injector;
|
|
1518
|
+
start = start.parentComponent;
|
|
1519
|
+
}
|
|
1520
|
+
return new NullInjector();
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* 创建一个上下文,用于在组件之间共享数据
|
|
1524
|
+
* @param providers 提供者,用于提供数据
|
|
1525
|
+
* @param scope 作用域,用于限制提供者的作用域
|
|
1526
|
+
* @param parentInjector 父注入器,用于自定义父注入器,默认从当前组件树中自动获取
|
|
1527
|
+
* @returns 一个上下文组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
|
|
1528
|
+
* @example
|
|
1529
|
+
* ```tsx
|
|
1530
|
+
* @Injectable()
|
|
1531
|
+
* class ExampleService {}
|
|
1532
|
+
*
|
|
1533
|
+
* function Child(props) {
|
|
1534
|
+
* const exampleService = inject(ExampleService)
|
|
1535
|
+
* console.log(exampleService)
|
|
1536
|
+
* return () => {
|
|
1537
|
+
* return <div>{props.children}</div>
|
|
1538
|
+
* }
|
|
1539
|
+
* }
|
|
1540
|
+
* function App() {
|
|
1541
|
+
* const Context = createContext([
|
|
1542
|
+
* ExampleService
|
|
1543
|
+
* ])
|
|
1544
|
+
* return () => {
|
|
1545
|
+
* return <Context>
|
|
1546
|
+
* <Child>test</Child>
|
|
1547
|
+
* </Context>
|
|
1548
|
+
* }
|
|
1549
|
+
* }
|
|
1550
|
+
* ```
|
|
1551
|
+
*/
|
|
1552
|
+
function createContext(providers, scope, parentInjector) {
|
|
1553
|
+
return function context(props) {
|
|
1554
|
+
const instance = getCurrentInstance();
|
|
1555
|
+
const injector = new ReflectiveInjector(parentInjector || getInjector(instance), providers, scope);
|
|
1556
|
+
injectMap.set(instance, injector);
|
|
1557
|
+
return () => {
|
|
1558
|
+
return props.children;
|
|
1559
|
+
};
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* 创建一个上下文提供者组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
|
|
1564
|
+
* @param params 提供者参数
|
|
1565
|
+
* @returns 一个上下文提供者组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
|
|
1566
|
+
* @example
|
|
1567
|
+
* ```tsx
|
|
1568
|
+
* const ExampleService = createContextProvider({
|
|
1569
|
+
* provide: ExampleService
|
|
1570
|
+
* })
|
|
1571
|
+
*
|
|
1572
|
+
* function Child() {
|
|
1573
|
+
* const exampleService = inject(ExampleService)
|
|
1574
|
+
* console.log(exampleService)
|
|
1575
|
+
* return () => {
|
|
1576
|
+
* return <div>{exampleService.name}</div>
|
|
1577
|
+
* }
|
|
1578
|
+
* }
|
|
1579
|
+
*
|
|
1580
|
+
* function App() {
|
|
1581
|
+
* const value = new ExampleService()
|
|
1582
|
+
* return () => {
|
|
1583
|
+
* return <ExampleService useValue={value}>
|
|
1584
|
+
* <Child/>
|
|
1585
|
+
* </ExampleService>
|
|
1586
|
+
* }
|
|
1587
|
+
* }
|
|
1588
|
+
*/
|
|
1589
|
+
function createContextProvider(params) {
|
|
1590
|
+
return function contextProvider(props) {
|
|
1591
|
+
let Context = createContext([{
|
|
1592
|
+
provide: params.provide,
|
|
1593
|
+
...props
|
|
1594
|
+
}]);
|
|
1595
|
+
watch(() => {
|
|
1596
|
+
return props.useClass || props.useFactory || props.useValue || props.useExisting;
|
|
1597
|
+
}, () => {
|
|
1598
|
+
Context = createContext([{
|
|
1599
|
+
provide: params.provide,
|
|
1600
|
+
...props
|
|
1601
|
+
}]);
|
|
1602
|
+
});
|
|
1603
|
+
return () => {
|
|
1604
|
+
return jsx(Context, { children: props.children });
|
|
1605
|
+
};
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
1610
|
+
* @param token 注入的 token
|
|
1611
|
+
* @param notFoundValue 未找到时的值
|
|
1612
|
+
* @param flags 注入标志
|
|
1613
|
+
* @returns 注入的值
|
|
1614
|
+
* @example
|
|
1615
|
+
* ```tsx
|
|
1616
|
+
* function ChildComponent() {
|
|
1617
|
+
* const exampleService = inject(ExampleService)
|
|
1618
|
+
* console.log(exampleService)
|
|
1619
|
+
* return () => {
|
|
1620
|
+
* return <div>{exampleService.name}</div>
|
|
1621
|
+
* }
|
|
1622
|
+
* }
|
|
1623
|
+
*/
|
|
1624
|
+
function inject(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
|
|
1625
|
+
return getInjector(getCurrentInstance()).get(token, notFoundValue, flags);
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* 给组件添加注解
|
|
1629
|
+
* @param annotation
|
|
1630
|
+
* @param componentSetup
|
|
1631
|
+
* @example
|
|
1632
|
+
* ```ts
|
|
1633
|
+
* export customScope = new Scope('scopeName')
|
|
1634
|
+
* export const App = withAnnotation({
|
|
1635
|
+
* scope: customScope,
|
|
1636
|
+
* providers: [
|
|
1637
|
+
* ExampleService
|
|
1638
|
+
* ]
|
|
1639
|
+
* }, function(props: Props) {
|
|
1640
|
+
* return () => {
|
|
1641
|
+
* return <div>...</div>
|
|
1642
|
+
* }
|
|
1643
|
+
* })
|
|
1644
|
+
* ```
|
|
1645
|
+
*/
|
|
1646
|
+
function withAnnotation(annotation, componentSetup) {
|
|
1647
|
+
return function(props) {
|
|
1648
|
+
const instance = getCurrentInstance();
|
|
1649
|
+
const injector = new ReflectiveInjector(injectMap.get(instance) || getInjector(instance.parentComponent), [{
|
|
1650
|
+
provide: Injector,
|
|
1651
|
+
useFactory() {
|
|
1652
|
+
return injector;
|
|
1653
|
+
}
|
|
1654
|
+
}, ...annotation.providers || []], annotation.scope);
|
|
1655
|
+
injectMap.set(instance, injector);
|
|
1656
|
+
return componentSetup(props);
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
//#endregion
|
|
1660
|
+
//#region src/base/injection-tokens.ts
|
|
1661
|
+
var NativeRenderer = class {};
|
|
1662
|
+
//#endregion
|
|
1663
|
+
//#region src/base/renderer.ts
|
|
1664
|
+
var listenerReg = /^on[A-Z]/;
|
|
1665
|
+
var nativeNodeRefRecord = /* @__PURE__ */ new Map();
|
|
1666
|
+
function createRenderer(component, nativeRenderer, namespace) {
|
|
1667
|
+
let isInit = true;
|
|
1668
|
+
return function render(host) {
|
|
1669
|
+
if (isInit) {
|
|
1670
|
+
isInit = false;
|
|
1671
|
+
componentRender(nativeRenderer, component, {
|
|
1672
|
+
type: ComponentAtomType,
|
|
1673
|
+
index: 0,
|
|
1674
|
+
nodeType: component.type,
|
|
1675
|
+
jsxNode: component,
|
|
1676
|
+
sibling: null,
|
|
1677
|
+
child: null,
|
|
1678
|
+
nativeNode: null,
|
|
1679
|
+
namespace
|
|
1680
|
+
}, {
|
|
1681
|
+
isParent: true,
|
|
1682
|
+
host,
|
|
1683
|
+
rootHost: host
|
|
1684
|
+
});
|
|
1685
|
+
} else deepUpdateByComponentDirtyTree(nativeRenderer, component, false);
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
1689
|
+
const { jsxNode, type } = atom;
|
|
1690
|
+
if (type === ComponentAtomType) {
|
|
1691
|
+
const component = new Component(parentComponent, jsxNode.type, jsxNode.props, jsxNode.key);
|
|
1692
|
+
atom.jsxNode = component;
|
|
1693
|
+
componentRender(nativeRenderer, component, atom, context);
|
|
1694
|
+
} else if (type === ElementAtomType) createElement(nativeRenderer, atom, parentComponent, context);
|
|
1695
|
+
else createTextNode(nativeRenderer, atom, context);
|
|
1696
|
+
}
|
|
1697
|
+
function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
|
|
1698
|
+
let child = atom.child;
|
|
1699
|
+
while (child) {
|
|
1700
|
+
buildView(nativeRenderer, parentComponent, child, context);
|
|
1701
|
+
child = child.sibling;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
|
|
1705
|
+
newAtom.child = createChildChain(component.rerender(), nativeRenderer, newAtom.namespace);
|
|
1706
|
+
diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
|
|
1707
|
+
}
|
|
1708
|
+
function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
|
|
1709
|
+
if (component.dirty) {
|
|
1710
|
+
const { atom, host, isParent, rootHost } = component.viewMetadata;
|
|
1711
|
+
const context = {
|
|
1712
|
+
host,
|
|
1713
|
+
isParent,
|
|
1714
|
+
rootHost
|
|
1715
|
+
};
|
|
1716
|
+
const diffAtom = atom.child;
|
|
1717
|
+
patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
|
|
1718
|
+
const next = atom.sibling;
|
|
1719
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1720
|
+
const view = next.jsxNode.viewMetadata;
|
|
1721
|
+
view.host = context.host;
|
|
1722
|
+
view.isParent = context.isParent;
|
|
1723
|
+
}
|
|
1724
|
+
component.rendered();
|
|
1725
|
+
} else if (component.changed) {
|
|
1726
|
+
component.changedSubComponents.forEach((child) => {
|
|
1727
|
+
deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
|
|
1728
|
+
});
|
|
1729
|
+
component.rendered();
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
|
|
1733
|
+
const commits = [];
|
|
1734
|
+
while (newAtom) {
|
|
1735
|
+
oldAtom = createChanges(newAtom, oldAtom, commits);
|
|
1736
|
+
newAtom = newAtom.sibling;
|
|
1737
|
+
}
|
|
1738
|
+
let dirtyDiffAtom = oldAtom;
|
|
1739
|
+
while (dirtyDiffAtom) {
|
|
1740
|
+
cleanView(nativeRenderer, dirtyDiffAtom, true);
|
|
1741
|
+
dirtyDiffAtom = dirtyDiffAtom.sibling;
|
|
1742
|
+
}
|
|
1743
|
+
let offset = 0;
|
|
1744
|
+
const len = commits.length;
|
|
1745
|
+
for (let i = 0; i < len; i++) {
|
|
1746
|
+
while (oldAtom) {
|
|
1747
|
+
if (oldAtom.index <= i) {
|
|
1748
|
+
offset--;
|
|
1749
|
+
oldAtom = oldAtom.sibling;
|
|
1750
|
+
continue;
|
|
1751
|
+
}
|
|
1752
|
+
break;
|
|
1753
|
+
}
|
|
1754
|
+
const { dirtyAtom, newAtom } = commits[i];
|
|
1755
|
+
if (dirtyAtom) switch (dirtyAtom.type) {
|
|
1756
|
+
case ElementAtomType:
|
|
1757
|
+
updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, dirtyAtom);
|
|
1758
|
+
break;
|
|
1759
|
+
case TextAtomType:
|
|
1760
|
+
updateText(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
|
|
1761
|
+
break;
|
|
1762
|
+
case ComponentAtomType:
|
|
1763
|
+
updateComponent(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
|
|
1764
|
+
break;
|
|
1765
|
+
}
|
|
1766
|
+
else {
|
|
1767
|
+
buildView(nativeRenderer, parentComponent, newAtom, context);
|
|
1768
|
+
offset++;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
function createChanges(newAtom, oldAtom, commits) {
|
|
1773
|
+
const startDiffAtom = oldAtom;
|
|
1774
|
+
let prev = null;
|
|
1775
|
+
while (oldAtom) {
|
|
1776
|
+
if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
|
|
1777
|
+
commits.push({
|
|
1778
|
+
dirtyAtom: oldAtom,
|
|
1779
|
+
newAtom
|
|
1780
|
+
});
|
|
1781
|
+
const next = oldAtom.sibling;
|
|
1782
|
+
if (!prev) return next;
|
|
1783
|
+
prev.sibling = next;
|
|
1784
|
+
return startDiffAtom;
|
|
1785
|
+
}
|
|
1786
|
+
prev = oldAtom;
|
|
1787
|
+
oldAtom = oldAtom.sibling;
|
|
1788
|
+
}
|
|
1789
|
+
commits.push({
|
|
1790
|
+
dirtyAtom: null,
|
|
1791
|
+
newAtom
|
|
1792
|
+
});
|
|
1793
|
+
return startDiffAtom;
|
|
1794
|
+
}
|
|
1795
|
+
function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
|
|
1796
|
+
const nativeNode = oldAtom.nativeNode;
|
|
1797
|
+
newAtom.nativeNode = nativeNode;
|
|
1798
|
+
if (needMove || newAtom.index - offset !== oldAtom.index) insertNode(nativeRenderer, newAtom, context);
|
|
1799
|
+
context.host = nativeNode;
|
|
1800
|
+
context.isParent = false;
|
|
1801
|
+
}
|
|
1802
|
+
function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
|
|
1803
|
+
const nativeNode = oldAtom.nativeNode;
|
|
1804
|
+
newAtom.nativeNode = nativeNode;
|
|
1805
|
+
if (needMove || newAtom.index - offset !== oldAtom.index) insertNode(nativeRenderer, newAtom, context);
|
|
1806
|
+
context.host = nativeNode;
|
|
1807
|
+
context.isParent = false;
|
|
1808
|
+
updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
|
|
1809
|
+
host: nativeNode,
|
|
1810
|
+
isParent: true,
|
|
1811
|
+
rootHost: context.rootHost
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
|
|
1815
|
+
const component = oldAtom.jsxNode;
|
|
1816
|
+
const portalHost = component.instance.$portalHost;
|
|
1817
|
+
context = portalHost ? {
|
|
1818
|
+
isParent: true,
|
|
1819
|
+
host: portalHost,
|
|
1820
|
+
rootHost: portalHost
|
|
1821
|
+
} : context;
|
|
1822
|
+
component.viewMetadata = {
|
|
1823
|
+
atom: newAtom,
|
|
1824
|
+
...context
|
|
1825
|
+
};
|
|
1826
|
+
const newProps = newAtom.jsxNode.props;
|
|
1827
|
+
newAtom.jsxNode = component;
|
|
1828
|
+
needMove = needMove || newAtom.index - offset !== oldAtom.index;
|
|
1829
|
+
const propsIsChanged = hasChange(newProps, component.props);
|
|
1830
|
+
if (propsIsChanged) component.updateProps(newProps);
|
|
1831
|
+
if (propsIsChanged || component.dirty) {
|
|
1832
|
+
patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
|
|
1833
|
+
const next = oldAtom.sibling;
|
|
1834
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1835
|
+
const view = next.jsxNode.viewMetadata;
|
|
1836
|
+
view.host = context.host;
|
|
1837
|
+
view.isParent = context.isParent;
|
|
1838
|
+
}
|
|
1839
|
+
} else {
|
|
1840
|
+
newAtom.child = oldAtom.child;
|
|
1841
|
+
reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !component.changedSubComponents.size);
|
|
1842
|
+
}
|
|
1843
|
+
component.rendered();
|
|
1844
|
+
}
|
|
1845
|
+
function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
|
|
1846
|
+
const updateContext = (atom) => {
|
|
1847
|
+
const jsxNode = atom.jsxNode;
|
|
1848
|
+
if (jsxNode instanceof Component) {
|
|
1849
|
+
reuseComponentView(nativeRenderer, atom.child, context, moveView, skipSubComponentDiff);
|
|
1850
|
+
if (!skipSubComponentDiff) deepUpdateByComponentDirtyTree(nativeRenderer, jsxNode, moveView);
|
|
1851
|
+
} else {
|
|
1852
|
+
if (moveView) insertNode(nativeRenderer, atom, context);
|
|
1853
|
+
if (!skipSubComponentDiff) reuseElementChildrenView(nativeRenderer, atom, context);
|
|
1854
|
+
context.isParent = false;
|
|
1855
|
+
context.host = atom.nativeNode;
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
while (child) {
|
|
1859
|
+
updateContext(child);
|
|
1860
|
+
child = child.sibling;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
function reuseElementChildrenView(nativeRenderer, atom, context) {
|
|
1864
|
+
let child = atom.child;
|
|
1865
|
+
while (child) {
|
|
1866
|
+
if (child.jsxNode instanceof Component) deepUpdateByComponentDirtyTree(nativeRenderer, child.jsxNode, false);
|
|
1867
|
+
else reuseElementChildrenView(nativeRenderer, child, context);
|
|
1868
|
+
child = child.sibling;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
function cleanElementChildren(atom, nativeRenderer) {
|
|
1872
|
+
let child = atom.child;
|
|
1873
|
+
nativeRenderer.cleanChildren(atom.nativeNode, atom.namespace);
|
|
1874
|
+
while (child) {
|
|
1875
|
+
cleanView(nativeRenderer, child, false);
|
|
1876
|
+
child = child.sibling;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
function cleanView(nativeRenderer, atom, needClean) {
|
|
1880
|
+
if (atom.type === ComponentAtomType) {
|
|
1881
|
+
const jsxNode = atom.jsxNode;
|
|
1882
|
+
if (jsxNode.instance.$portalHost) needClean = true;
|
|
1883
|
+
cleanChildren(atom, nativeRenderer, needClean);
|
|
1884
|
+
jsxNode.destroy();
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
if (needClean) {
|
|
1888
|
+
nativeRenderer.remove(atom.nativeNode, atom.namespace);
|
|
1889
|
+
needClean = false;
|
|
1890
|
+
}
|
|
1891
|
+
if (atom.type === ElementAtomType) {
|
|
1892
|
+
const record = nativeNodeRefRecord.get(atom);
|
|
1893
|
+
if (record) record.forEach((fn) => {
|
|
1894
|
+
if (typeof fn === "function") fn();
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
cleanChildren(atom, nativeRenderer, needClean);
|
|
1898
|
+
}
|
|
1899
|
+
function cleanChildren(atom, nativeRenderer, needClean) {
|
|
1900
|
+
let child = atom.child;
|
|
1901
|
+
while (child) {
|
|
1902
|
+
cleanView(nativeRenderer, child, needClean);
|
|
1903
|
+
child = child.sibling;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
function componentRender(nativeRenderer, component, from, context) {
|
|
1907
|
+
component.render((template, portalHost) => {
|
|
1908
|
+
from.child = createChildChain(template, nativeRenderer, from.namespace);
|
|
1909
|
+
context = portalHost ? {
|
|
1910
|
+
isParent: true,
|
|
1911
|
+
host: portalHost,
|
|
1912
|
+
rootHost: portalHost
|
|
1913
|
+
} : context;
|
|
1914
|
+
component.viewMetadata = {
|
|
1915
|
+
atom: from,
|
|
1916
|
+
...context
|
|
1917
|
+
};
|
|
1918
|
+
let child = from.child;
|
|
1919
|
+
while (child) {
|
|
1920
|
+
buildView(nativeRenderer, component, child, context);
|
|
1921
|
+
child = child.sibling;
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key) {
|
|
1926
|
+
const atom = {
|
|
1927
|
+
type,
|
|
1928
|
+
index: prevAtom.index + 1,
|
|
1929
|
+
jsxNode,
|
|
1930
|
+
sibling: null,
|
|
1931
|
+
child: null,
|
|
1932
|
+
nativeNode: null,
|
|
1933
|
+
namespace,
|
|
1934
|
+
nodeType,
|
|
1935
|
+
key
|
|
1936
|
+
};
|
|
1937
|
+
prevAtom.sibling = atom;
|
|
1938
|
+
return atom;
|
|
1939
|
+
}
|
|
1940
|
+
function createChainByNode(jsxNode, prevAtom, nativeRenderer, elementNamespace) {
|
|
1941
|
+
const type = typeof jsxNode;
|
|
1942
|
+
if (jsxNode != null && type !== "boolean") {
|
|
1943
|
+
if (type === "string") return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, elementNamespace);
|
|
1944
|
+
if (type === "object") {
|
|
1945
|
+
if (Array.isArray(jsxNode)) return createChainByChildren(jsxNode, prevAtom, nativeRenderer, elementNamespace);
|
|
1946
|
+
const nodeType = typeof jsxNode.type;
|
|
1947
|
+
if (nodeType === "string") return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, nativeRenderer.getNameSpace(jsxNode.type, elementNamespace), jsxNode.key);
|
|
1948
|
+
else if (nodeType === "function") return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace, jsxNode.key);
|
|
1949
|
+
}
|
|
1950
|
+
const text = String(jsxNode);
|
|
1951
|
+
return createChainByJSXNode(TextAtomType, text, text, prevAtom, elementNamespace);
|
|
1952
|
+
}
|
|
1953
|
+
return prevAtom;
|
|
1954
|
+
}
|
|
1955
|
+
function createChainByChildren(children, prevAtom, nativeRenderer, elementNamespace) {
|
|
1956
|
+
const len = children.length;
|
|
1957
|
+
for (let i = 0; i < len; i++) {
|
|
1958
|
+
const item = children[i];
|
|
1959
|
+
prevAtom = createChainByNode(item, prevAtom, nativeRenderer, elementNamespace);
|
|
1960
|
+
}
|
|
1961
|
+
return prevAtom;
|
|
1962
|
+
}
|
|
1963
|
+
function createChildChain(template, nativeRenderer, namespace) {
|
|
1964
|
+
const beforeAtom = {
|
|
1965
|
+
sibling: null,
|
|
1966
|
+
index: -1
|
|
1967
|
+
};
|
|
1968
|
+
createChainByNode(template, beforeAtom, nativeRenderer, namespace);
|
|
1969
|
+
return beforeAtom.sibling;
|
|
1970
|
+
}
|
|
1971
|
+
function insertNode(nativeRenderer, atom, context) {
|
|
1972
|
+
if (context.isParent) if (context.host === context.rootHost) nativeRenderer.appendChild(context.host, atom.nativeNode, atom.namespace);
|
|
1973
|
+
else nativeRenderer.prependChild(context.host, atom.nativeNode, atom.namespace);
|
|
1974
|
+
else nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
|
|
1975
|
+
}
|
|
1976
|
+
function createElementChildren(type, children, nativeRenderer, namespace) {
|
|
1977
|
+
return createChildChain(children, nativeRenderer, nativeRenderer.getNameSpace(type, namespace));
|
|
1978
|
+
}
|
|
1979
|
+
function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
1980
|
+
const { namespace, jsxNode } = atom;
|
|
1981
|
+
const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
|
|
1982
|
+
const props = jsxNode.props;
|
|
1983
|
+
let bindingRefs;
|
|
1984
|
+
for (const key in props) {
|
|
1985
|
+
if (key === "children") {
|
|
1986
|
+
atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
|
|
1987
|
+
continue;
|
|
1988
|
+
}
|
|
1989
|
+
if (key === "class") {
|
|
1990
|
+
const className = classToString(props[key]);
|
|
1991
|
+
if (className) nativeRenderer.setClass(nativeNode, className, namespace);
|
|
1992
|
+
continue;
|
|
1993
|
+
}
|
|
1994
|
+
if (key === "style") {
|
|
1995
|
+
const style = styleToObject(props.style);
|
|
1996
|
+
for (const key in style) nativeRenderer.setStyle(nativeNode, key, style[key], namespace);
|
|
1997
|
+
continue;
|
|
1998
|
+
}
|
|
1999
|
+
if (listenerReg.test(key)) {
|
|
2000
|
+
const listener = props[key];
|
|
2001
|
+
if (typeof listener === "function") nativeRenderer.listen(nativeNode, key, listener, namespace);
|
|
2002
|
+
continue;
|
|
2003
|
+
}
|
|
2004
|
+
if (key === "ref") {
|
|
2005
|
+
bindingRefs = props[key];
|
|
2006
|
+
continue;
|
|
2007
|
+
}
|
|
2008
|
+
nativeRenderer.setProperty(nativeNode, key, props[key], namespace);
|
|
2009
|
+
}
|
|
2010
|
+
atom.nativeNode = nativeNode;
|
|
2011
|
+
insertNode(nativeRenderer, atom, context);
|
|
2012
|
+
buildElementChildren(atom, nativeRenderer, parentComponent, {
|
|
2013
|
+
isParent: true,
|
|
2014
|
+
host: nativeNode,
|
|
2015
|
+
rootHost: context.rootHost
|
|
2016
|
+
});
|
|
2017
|
+
context.host = nativeNode;
|
|
2018
|
+
context.isParent = false;
|
|
2019
|
+
const refEffects = /* @__PURE__ */ new Map();
|
|
2020
|
+
nativeNodeRefRecord.set(atom, refEffects);
|
|
2021
|
+
applyRefs(bindingRefs, nativeNode, refEffects);
|
|
2022
|
+
}
|
|
2023
|
+
function createTextNode(nativeRenderer, atom, context) {
|
|
2024
|
+
const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
|
|
2025
|
+
atom.nativeNode = nativeNode;
|
|
2026
|
+
insertNode(nativeRenderer, atom, context);
|
|
2027
|
+
context.host = nativeNode;
|
|
2028
|
+
context.isParent = false;
|
|
2029
|
+
}
|
|
2030
|
+
function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context) {
|
|
2031
|
+
const newVNode = newAtom.jsxNode;
|
|
2032
|
+
const isSvg = newAtom.namespace;
|
|
2033
|
+
const nativeNode = newAtom.nativeNode;
|
|
2034
|
+
const oldVNode = oldAtom.jsxNode;
|
|
2035
|
+
if (newVNode === oldVNode) {
|
|
2036
|
+
newAtom.child = oldAtom.child;
|
|
2037
|
+
reuseElementChildrenView(nativeRenderer, newAtom, context);
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
let bindRefs;
|
|
2041
|
+
let updatedChildren = false;
|
|
2042
|
+
comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
|
|
2043
|
+
if (key === "children") {
|
|
2044
|
+
updatedChildren = true;
|
|
2045
|
+
cleanElementChildren(oldAtom, nativeRenderer);
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
if (key === "class") {
|
|
2049
|
+
nativeRenderer.setClass(nativeNode, "", isSvg);
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
if (key === "style") {
|
|
2053
|
+
for (const styleName in styleToObject(oldValue)) nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
if (listenerReg.test(key)) {
|
|
2057
|
+
if (typeof oldValue === "function") nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
if (key === "ref") return;
|
|
2061
|
+
nativeRenderer.removeProperty(nativeNode, key, isSvg);
|
|
2062
|
+
}, (key, value) => {
|
|
2063
|
+
if (key === "children") {
|
|
2064
|
+
updatedChildren = true;
|
|
2065
|
+
newAtom.child = createElementChildren(newVNode.type, value, nativeRenderer, isSvg);
|
|
2066
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
if (key === "class") {
|
|
2070
|
+
nativeRenderer.setClass(nativeNode, classToString(value), isSvg);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
if (key === "style") {
|
|
2074
|
+
const styleObj = styleToObject(value);
|
|
2075
|
+
for (const styleName in styleObj) nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
if (listenerReg.test(key)) {
|
|
2079
|
+
if (typeof value === "function") nativeRenderer.listen(nativeNode, key, value, isSvg);
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
if (key === "ref") {
|
|
2083
|
+
bindRefs = value;
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
nativeRenderer.setProperty(nativeNode, key, value, isSvg);
|
|
2087
|
+
}, (key, newValue, oldValue) => {
|
|
2088
|
+
if (key === "children") {
|
|
2089
|
+
updatedChildren = true;
|
|
2090
|
+
newAtom.child = createElementChildren(newVNode.type, newValue, nativeRenderer, isSvg);
|
|
2091
|
+
if (!newAtom.child) cleanElementChildren(oldAtom, nativeRenderer);
|
|
2092
|
+
else if (!oldAtom.child) buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
2093
|
+
else diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
if (key === "class") {
|
|
2097
|
+
const oldClassName = classToString(oldValue);
|
|
2098
|
+
const newClassName = classToString(newValue);
|
|
2099
|
+
if (oldClassName !== newClassName) nativeRenderer.setClass(nativeNode, newClassName, isSvg);
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
if (key === "style") {
|
|
2103
|
+
comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), (styleName) => {
|
|
2104
|
+
nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
|
|
2105
|
+
}, (styleName, styleValue) => {
|
|
2106
|
+
nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
|
|
2107
|
+
}, (styleName, styleValue) => {
|
|
2108
|
+
nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
|
|
2109
|
+
});
|
|
2110
|
+
return;
|
|
2111
|
+
}
|
|
2112
|
+
if (listenerReg.test(key)) {
|
|
2113
|
+
nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
|
|
2114
|
+
nativeRenderer.listen(nativeNode, key, newValue, isSvg);
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
if (key === "ref") {
|
|
2118
|
+
bindRefs = newValue;
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
|
|
2122
|
+
});
|
|
2123
|
+
if (!updatedChildren) newAtom.child = oldAtom.child;
|
|
2124
|
+
let refEffects = nativeNodeRefRecord.get(oldAtom);
|
|
2125
|
+
if (!refEffects) refEffects = /* @__PURE__ */ new Map();
|
|
2126
|
+
nativeNodeRefRecord.delete(oldAtom);
|
|
2127
|
+
nativeNodeRefRecord.set(newAtom, refEffects);
|
|
2128
|
+
updateRefs(bindRefs, nativeNode, refEffects);
|
|
2129
|
+
}
|
|
2130
|
+
//#endregion
|
|
2131
|
+
//#region src/base/root.component.ts
|
|
2132
|
+
/**
|
|
2133
|
+
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
2134
|
+
*/
|
|
2135
|
+
var RootComponent = class extends Component {
|
|
2136
|
+
constructor(factory, refresh) {
|
|
2137
|
+
super(null, factory, {});
|
|
2138
|
+
this.refresh = refresh;
|
|
2139
|
+
}
|
|
2140
|
+
markAsChanged(changedComponent) {
|
|
2141
|
+
this._changed = true;
|
|
2142
|
+
if (changedComponent) this.changedSubComponents.add(changedComponent);
|
|
2143
|
+
this.refresh();
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
//#endregion
|
|
2147
|
+
//#region src/viewfly.ts
|
|
2148
|
+
var viewflyErrorFn = makeError("Viewfly");
|
|
2149
|
+
function viewfly(config) {
|
|
2150
|
+
const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
|
|
2151
|
+
const modules = [];
|
|
2152
|
+
let destroyed = false;
|
|
2153
|
+
let appHost = null;
|
|
2154
|
+
const rootProviders = [];
|
|
2155
|
+
const rootComponent = new RootComponent(() => {
|
|
2156
|
+
const rootContext = createContext(rootProviders, null, context);
|
|
2157
|
+
return () => {
|
|
2158
|
+
return jsx(rootContext, { children: destroyed ? null : root });
|
|
2159
|
+
};
|
|
2160
|
+
}, function() {
|
|
2161
|
+
if (destroyed || !autoUpdate) return;
|
|
2162
|
+
nextTick(() => {
|
|
2163
|
+
render(appHost);
|
|
2164
|
+
});
|
|
2165
|
+
});
|
|
2166
|
+
const render = createRenderer(rootComponent, nativeRenderer, config.elementNamespace);
|
|
2167
|
+
let isStarted = false;
|
|
2168
|
+
let task = null;
|
|
2169
|
+
function nextTick(callback) {
|
|
2170
|
+
if (task !== null) return;
|
|
2171
|
+
task = Promise.resolve().then(() => {
|
|
2172
|
+
task = null;
|
|
2173
|
+
callback();
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
const app = {
|
|
2177
|
+
provide(providers) {
|
|
2178
|
+
providers = Array.isArray(providers) ? providers : [providers];
|
|
2179
|
+
rootProviders.push(...providers);
|
|
2180
|
+
return app;
|
|
2181
|
+
},
|
|
2182
|
+
use(module) {
|
|
2183
|
+
if (Array.isArray(module)) modules.push(...module);
|
|
2184
|
+
else modules.push(module);
|
|
2185
|
+
return app;
|
|
2186
|
+
},
|
|
2187
|
+
mount(host) {
|
|
2188
|
+
if (isStarted) throw viewflyErrorFn("application has already started.");
|
|
2189
|
+
for (const module of modules) module.setup?.(app);
|
|
2190
|
+
isStarted = true;
|
|
2191
|
+
appHost = host;
|
|
2192
|
+
render(host);
|
|
2193
|
+
for (const module of modules) module.onAfterStartup?.(app);
|
|
2194
|
+
if (!autoUpdate) return app;
|
|
2195
|
+
return app;
|
|
2196
|
+
},
|
|
2197
|
+
render() {
|
|
2198
|
+
if (appHost) render(appHost);
|
|
2199
|
+
return app;
|
|
2200
|
+
},
|
|
2201
|
+
destroy() {
|
|
2202
|
+
destroyed = true;
|
|
2203
|
+
rootComponent.markAsDirtied();
|
|
2204
|
+
app.render();
|
|
2205
|
+
for (const module of modules) module.onDestroy?.();
|
|
2206
|
+
}
|
|
2207
|
+
};
|
|
2208
|
+
return app;
|
|
2209
|
+
}
|
|
2210
|
+
//#endregion
|
|
2211
|
+
//#region src/reactive/computed.ts
|
|
2212
|
+
/**
|
|
2213
|
+
* 创建一个 computed,当依赖的值发生变化时,会重新计算值。
|
|
2214
|
+
* computed 会返回一个对象,对象的 value 属性是计算的值。
|
|
2215
|
+
* @param getter 计算函数,用于计算值
|
|
2216
|
+
* @returns 一个对象,对象的 value 属性是计算的值
|
|
2217
|
+
*/
|
|
2218
|
+
function computed(getter) {
|
|
2219
|
+
return { get value() {
|
|
2220
|
+
return getter();
|
|
2221
|
+
} };
|
|
2222
|
+
}
|
|
2223
|
+
//#endregion
|
|
2224
|
+
//#region src/reactive/shallow-reactive.ts
|
|
2225
|
+
var defaultShallowObjectReactiveHandler = new ObjectReactiveHandler({
|
|
2226
|
+
readonly: false,
|
|
2227
|
+
shallow: true
|
|
2228
|
+
});
|
|
2229
|
+
var defaultShallowArrayReactiveHandler = new ArrayReactiveHandler({
|
|
2230
|
+
readonly: false,
|
|
2231
|
+
shallow: true
|
|
2232
|
+
});
|
|
2233
|
+
var defaultShallowMapReactiveHandler = new MapReactiveHandler({
|
|
2234
|
+
readonly: false,
|
|
2235
|
+
shallow: true
|
|
2236
|
+
});
|
|
2237
|
+
var defaultShallowSetReactiveHandler = new SetReactiveHandler({
|
|
2238
|
+
readonly: false,
|
|
2239
|
+
shallow: true
|
|
2240
|
+
});
|
|
2241
|
+
function shallowReactive(raw) {
|
|
2242
|
+
if (isReactive(raw)) return raw;
|
|
2243
|
+
let proxy = rawToProxyCache.get(raw);
|
|
2244
|
+
if (proxy) return proxy;
|
|
2245
|
+
switch (getStringType(raw)) {
|
|
2246
|
+
case "[object Object]":
|
|
2247
|
+
proxy = new Proxy(raw, defaultShallowObjectReactiveHandler);
|
|
2248
|
+
break;
|
|
2249
|
+
case "[object Array]":
|
|
2250
|
+
proxy = new Proxy(raw, defaultShallowArrayReactiveHandler);
|
|
2251
|
+
break;
|
|
2252
|
+
case "[object Set]":
|
|
2253
|
+
case "[object WeakSet]":
|
|
2254
|
+
proxy = new Proxy(raw, defaultShallowSetReactiveHandler);
|
|
2255
|
+
break;
|
|
2256
|
+
case "[object Map]":
|
|
2257
|
+
case "[object WeakMap]":
|
|
2258
|
+
proxy = new Proxy(raw, defaultShallowMapReactiveHandler);
|
|
2259
|
+
break;
|
|
2260
|
+
default: return raw;
|
|
2261
|
+
}
|
|
2262
|
+
rawToProxyCache.set(raw, proxy);
|
|
2263
|
+
proxyToRawCache.set(proxy, raw);
|
|
2264
|
+
return proxy;
|
|
2265
|
+
}
|
|
2266
|
+
//#endregion
|
|
2267
|
+
//#region src/reactive/signal.ts
|
|
2268
|
+
/**
|
|
2269
|
+
* 组件状态管理器
|
|
2270
|
+
* @param state 初始状态
|
|
2271
|
+
* @example
|
|
2272
|
+
* ```tsx
|
|
2273
|
+
* function App() {
|
|
2274
|
+
* // 初始化状态
|
|
2275
|
+
* const state = createSignal(1)
|
|
2276
|
+
*
|
|
2277
|
+
* return () => {
|
|
2278
|
+
* <div>
|
|
2279
|
+
* <div>当前值为:{state()}</div>
|
|
2280
|
+
* <div>
|
|
2281
|
+
* <button type="button" onClick={() => {
|
|
2282
|
+
* // 当点击时更新状态
|
|
2283
|
+
* state.set(state() + 1)
|
|
2284
|
+
* }
|
|
2285
|
+
* }>updateState</button>
|
|
2286
|
+
* </div>
|
|
2287
|
+
* </div>
|
|
2288
|
+
* }
|
|
2289
|
+
* }
|
|
2290
|
+
*/
|
|
2291
|
+
function createSignal(state) {
|
|
2292
|
+
const ref = shallowReactive({ value: state });
|
|
2293
|
+
function signal() {
|
|
2294
|
+
return ref.value;
|
|
2295
|
+
}
|
|
2296
|
+
signal.set = function(newValue) {
|
|
2297
|
+
ref.value = newValue;
|
|
2298
|
+
};
|
|
2299
|
+
return signal;
|
|
2300
|
+
}
|
|
2301
|
+
//#endregion
|
|
2302
|
+
export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };
|