@viewfly/core 0.0.1-alpha.12 → 0.0.1-alpha.13
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 +1 -1
- package/package.json +2 -5
- package/bundles/_utils/make-error.d.ts +0 -1
- package/bundles/foundation/_api.d.ts +0 -2
- package/bundles/foundation/_utils.d.ts +0 -9
- package/bundles/foundation/injection-tokens.d.ts +0 -17
- package/bundles/foundation/renderer.d.ts +0 -33
- package/bundles/index.esm.js +0 -1228
- package/bundles/index.js +0 -1257
- package/bundles/model/_api.d.ts +0 -3
- package/bundles/model/component.d.ts +0 -218
- package/bundles/model/jsx-element.d.ts +0 -31
- package/bundles/model/root.component.d.ts +0 -11
- package/bundles/public-api.d.ts +0 -6
- package/bundles/viewfly.d.ts +0 -37
package/bundles/index.js
DELETED
|
@@ -1,1257 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
require('reflect-metadata');
|
|
4
|
-
var di = require('@tanbo/di');
|
|
5
|
-
var stream = require('@tanbo/stream');
|
|
6
|
-
|
|
7
|
-
function makeError(name) {
|
|
8
|
-
return function viewflyError(message) {
|
|
9
|
-
const error = new Error(message);
|
|
10
|
-
error.name = `[ViewflyError: ${name}]`;
|
|
11
|
-
error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
|
|
12
|
-
return error;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
class NativeRenderer {
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/******************************************************************************
|
|
20
|
-
Copyright (c) Microsoft Corporation.
|
|
21
|
-
|
|
22
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
23
|
-
purpose with or without fee is hereby granted.
|
|
24
|
-
|
|
25
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
26
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
27
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
28
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
29
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
30
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
31
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
32
|
-
***************************************************************************** */
|
|
33
|
-
/* global Reflect, Promise */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
function __decorate(decorators, target, key, desc) {
|
|
37
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
38
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
39
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
40
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function __metadata(metadataKey, metadataValue) {
|
|
44
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const componentSetupStack = [];
|
|
48
|
-
const componentRendingStack = [];
|
|
49
|
-
const derivedStack = [];
|
|
50
|
-
const componentErrorFn = makeError('component');
|
|
51
|
-
function getSetupContext(need = true) {
|
|
52
|
-
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
53
|
-
if (!current && need) {
|
|
54
|
-
// 防止因外部捕获异常引引起的缓存未清理的问题
|
|
55
|
-
componentRendingStack.pop();
|
|
56
|
-
throw componentErrorFn('cannot be called outside the component!');
|
|
57
|
-
}
|
|
58
|
-
return current;
|
|
59
|
-
}
|
|
60
|
-
function getRendingContext() {
|
|
61
|
-
return componentRendingStack[componentRendingStack.length - 1];
|
|
62
|
-
}
|
|
63
|
-
function getDerivedContext() {
|
|
64
|
-
return derivedStack[derivedStack.length - 1];
|
|
65
|
-
}
|
|
66
|
-
class JSXComponent {
|
|
67
|
-
constructor(createInstance) {
|
|
68
|
-
this.createInstance = createInstance;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
73
|
-
*/
|
|
74
|
-
class Component extends di.ReflectiveInjector {
|
|
75
|
-
get dirty() {
|
|
76
|
-
return this._dirty;
|
|
77
|
-
}
|
|
78
|
-
get changed() {
|
|
79
|
-
return this._changed;
|
|
80
|
-
}
|
|
81
|
-
constructor(context, setup, props, key) {
|
|
82
|
-
super(context, []);
|
|
83
|
-
this.setup = setup;
|
|
84
|
-
this.props = props;
|
|
85
|
-
this.key = key;
|
|
86
|
-
this.$$typeOf = this.setup;
|
|
87
|
-
this.destroyCallbacks = [];
|
|
88
|
-
this.mountCallbacks = [];
|
|
89
|
-
this.propsChangedCallbacks = [];
|
|
90
|
-
this.updatedCallbacks = [];
|
|
91
|
-
this._dirty = true;
|
|
92
|
-
this._changed = true;
|
|
93
|
-
this.updatedDestroyCallbacks = [];
|
|
94
|
-
this.propsChangedDestroyCallbacks = [];
|
|
95
|
-
this.isFirstRending = true;
|
|
96
|
-
this.parentComponent = this.parentInjector;
|
|
97
|
-
}
|
|
98
|
-
is(target) {
|
|
99
|
-
return target.$$typeOf === this.$$typeOf;
|
|
100
|
-
}
|
|
101
|
-
addProvide(providers) {
|
|
102
|
-
providers = Array.isArray(providers) ? providers : [providers];
|
|
103
|
-
providers.forEach(p => {
|
|
104
|
-
this.normalizedProviders.push(di.normalizeProvider(p));
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
init() {
|
|
108
|
-
const self = this;
|
|
109
|
-
const props = new Proxy(this.props, {
|
|
110
|
-
get(_, key) {
|
|
111
|
-
if (self.props) {
|
|
112
|
-
return self.props[key];
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
set() {
|
|
116
|
-
// 防止因外部捕获异常引引起的缓存未清理的问题
|
|
117
|
-
if (isSetup) {
|
|
118
|
-
componentSetupStack.pop();
|
|
119
|
-
}
|
|
120
|
-
if (isRending) {
|
|
121
|
-
componentRendingStack.pop();
|
|
122
|
-
}
|
|
123
|
-
throw componentErrorFn('component props is readonly!');
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
componentSetupStack.push(this);
|
|
127
|
-
let isSetup = true;
|
|
128
|
-
const render = this.setup(props);
|
|
129
|
-
isSetup = false;
|
|
130
|
-
componentSetupStack.pop();
|
|
131
|
-
componentRendingStack.push(this);
|
|
132
|
-
let isRending = true;
|
|
133
|
-
const template = render();
|
|
134
|
-
isRending = false;
|
|
135
|
-
componentRendingStack.pop();
|
|
136
|
-
return {
|
|
137
|
-
template,
|
|
138
|
-
render: () => {
|
|
139
|
-
componentRendingStack.push(this);
|
|
140
|
-
isRending = true;
|
|
141
|
-
const template = render();
|
|
142
|
-
isRending = false;
|
|
143
|
-
componentRendingStack.pop();
|
|
144
|
-
return template;
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
markAsDirtied() {
|
|
149
|
-
this._dirty = true;
|
|
150
|
-
this.markAsChanged();
|
|
151
|
-
}
|
|
152
|
-
markAsChanged() {
|
|
153
|
-
this._changed = true;
|
|
154
|
-
this.parentComponent.markAsChanged();
|
|
155
|
-
}
|
|
156
|
-
rendered() {
|
|
157
|
-
const is = this.isFirstRending;
|
|
158
|
-
this.isFirstRending = false;
|
|
159
|
-
this._dirty = this._changed = false;
|
|
160
|
-
if (is) {
|
|
161
|
-
this.invokeUpdatedHooks();
|
|
162
|
-
this.invokeMountHooks();
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
this.invokeUpdatedHooks();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
invokePropsChangedHooks(newProps) {
|
|
169
|
-
const oldProps = this.props;
|
|
170
|
-
this.props = newProps;
|
|
171
|
-
this.propsChangedDestroyCallbacks.forEach(fn => {
|
|
172
|
-
fn();
|
|
173
|
-
});
|
|
174
|
-
this.propsChangedDestroyCallbacks = [];
|
|
175
|
-
for (const fn of this.propsChangedCallbacks) {
|
|
176
|
-
const destroyFn = fn(newProps, oldProps);
|
|
177
|
-
if (typeof destroyFn === 'function') {
|
|
178
|
-
this.propsChangedDestroyCallbacks.push(destroyFn);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
destroy() {
|
|
183
|
-
this.updatedDestroyCallbacks.forEach(fn => {
|
|
184
|
-
fn();
|
|
185
|
-
});
|
|
186
|
-
this.updatedDestroyCallbacks = [];
|
|
187
|
-
this.propsChangedDestroyCallbacks.forEach(fn => {
|
|
188
|
-
fn();
|
|
189
|
-
});
|
|
190
|
-
this.propsChangedDestroyCallbacks = [];
|
|
191
|
-
for (const fn of this.destroyCallbacks) {
|
|
192
|
-
fn();
|
|
193
|
-
}
|
|
194
|
-
this.updatedCallbacks = [];
|
|
195
|
-
this.mountCallbacks = [];
|
|
196
|
-
this.updatedCallbacks = [];
|
|
197
|
-
}
|
|
198
|
-
invokeMountHooks() {
|
|
199
|
-
for (const fn of this.mountCallbacks) {
|
|
200
|
-
const destroyFn = fn();
|
|
201
|
-
if (typeof destroyFn === 'function') {
|
|
202
|
-
this.destroyCallbacks.push(destroyFn);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
invokeUpdatedHooks() {
|
|
207
|
-
this.updatedDestroyCallbacks.forEach(fn => {
|
|
208
|
-
fn();
|
|
209
|
-
});
|
|
210
|
-
this.updatedDestroyCallbacks = [];
|
|
211
|
-
for (const fn of this.updatedCallbacks) {
|
|
212
|
-
const destroyFn = fn();
|
|
213
|
-
if (typeof destroyFn === 'function') {
|
|
214
|
-
this.updatedDestroyCallbacks.push(destroyFn);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* 当组件第一次渲染完成时触发
|
|
221
|
-
* @param callback
|
|
222
|
-
* ```tsx
|
|
223
|
-
* function App() {
|
|
224
|
-
* onMount(() => {
|
|
225
|
-
* console.log('App mounted!')
|
|
226
|
-
* })
|
|
227
|
-
* return () => <div>...</div>
|
|
228
|
-
* }
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
function onMounted(callback) {
|
|
232
|
-
const component = getSetupContext();
|
|
233
|
-
component.mountCallbacks.push(callback);
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* 当组件视图更新后调用
|
|
237
|
-
* @param callback
|
|
238
|
-
* ```tsx
|
|
239
|
-
* function App() {
|
|
240
|
-
* onUpdated(() => {
|
|
241
|
-
* console.log('App updated!')
|
|
242
|
-
* return () => {
|
|
243
|
-
* console.log('destroy prev update!')
|
|
244
|
-
* }
|
|
245
|
-
* })
|
|
246
|
-
* return () => <div>...</div>
|
|
247
|
-
* }
|
|
248
|
-
* ```
|
|
249
|
-
*/
|
|
250
|
-
function onUpdated(callback) {
|
|
251
|
-
const component = getSetupContext();
|
|
252
|
-
component.updatedCallbacks.push(callback);
|
|
253
|
-
return () => {
|
|
254
|
-
const index = component.updatedCallbacks.indexOf(callback);
|
|
255
|
-
if (index > -1) {
|
|
256
|
-
component.updatedCallbacks.splice(index, 1);
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* 当组件 props 更新地调用
|
|
262
|
-
* @param callback
|
|
263
|
-
* @example
|
|
264
|
-
* ```tsx
|
|
265
|
-
* function YourComponent(props) {
|
|
266
|
-
* onPropsChanged((currentProps, prevProps) => {
|
|
267
|
-
* console.log(currentProps, prevProps)
|
|
268
|
-
*
|
|
269
|
-
* return () => {
|
|
270
|
-
* console.log('destroy prev changed!')
|
|
271
|
-
* }
|
|
272
|
-
* })
|
|
273
|
-
* return () => {
|
|
274
|
-
* return <div>xxx</div>
|
|
275
|
-
* }
|
|
276
|
-
* }
|
|
277
|
-
* ```
|
|
278
|
-
*/
|
|
279
|
-
function onPropsChanged(callback) {
|
|
280
|
-
const component = getSetupContext();
|
|
281
|
-
component.propsChangedCallbacks.push(callback);
|
|
282
|
-
return () => {
|
|
283
|
-
const index = component.propsChangedCallbacks.indexOf(callback);
|
|
284
|
-
if (index > -1) {
|
|
285
|
-
component.propsChangedCallbacks.splice(index, 1);
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* 当组件销毁时调用回调函数
|
|
291
|
-
* @param callback
|
|
292
|
-
*/
|
|
293
|
-
function onDestroy(callback) {
|
|
294
|
-
const component = getSetupContext();
|
|
295
|
-
component.destroyCallbacks.push(callback);
|
|
296
|
-
}
|
|
297
|
-
class Ref {
|
|
298
|
-
constructor(callback) {
|
|
299
|
-
this.callback = callback;
|
|
300
|
-
this.unBindMap = new WeakMap();
|
|
301
|
-
this.targetCaches = new Set();
|
|
302
|
-
}
|
|
303
|
-
bind(value) {
|
|
304
|
-
if (typeof value !== 'object' || value === null) {
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
if (this.targetCaches.has(value)) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
const unBindFn = this.callback(value);
|
|
311
|
-
if (typeof unBindFn === 'function') {
|
|
312
|
-
this.unBindMap.set(value, unBindFn);
|
|
313
|
-
}
|
|
314
|
-
this.targetCaches.add(value);
|
|
315
|
-
}
|
|
316
|
-
unBind(value) {
|
|
317
|
-
this.targetCaches.delete(value);
|
|
318
|
-
const unBindFn = this.unBindMap.get(value);
|
|
319
|
-
this.unBindMap.delete(value);
|
|
320
|
-
if (typeof unBindFn === 'function') {
|
|
321
|
-
unBindFn();
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* 用于节点渲染完成时获取 DOM 节点
|
|
327
|
-
* @param callback 获取 DOM 节点的回调函数
|
|
328
|
-
* @example
|
|
329
|
-
* ```tsx
|
|
330
|
-
* function App() {
|
|
331
|
-
* const ref = useRef(node => {
|
|
332
|
-
* function fn() {
|
|
333
|
-
* // do something...
|
|
334
|
-
* }
|
|
335
|
-
* node.addEventListener('click', fn)
|
|
336
|
-
* return () => {
|
|
337
|
-
* node.removeEventListener('click', fn)
|
|
338
|
-
* }
|
|
339
|
-
* })
|
|
340
|
-
* return () => {
|
|
341
|
-
* return <div ref={ref}>xxx</div>
|
|
342
|
-
* }
|
|
343
|
-
* }
|
|
344
|
-
* ```
|
|
345
|
-
*/
|
|
346
|
-
function useRef(callback) {
|
|
347
|
-
return new Ref(callback);
|
|
348
|
-
}
|
|
349
|
-
const depsKey = Symbol('deps');
|
|
350
|
-
/**
|
|
351
|
-
* 组件状态管理器
|
|
352
|
-
* @param state 初始状态
|
|
353
|
-
* @example
|
|
354
|
-
* ```tsx
|
|
355
|
-
* function App() {
|
|
356
|
-
* // 初始化状态
|
|
357
|
-
* const state = useSignal(1)
|
|
358
|
-
*
|
|
359
|
-
* return () => {
|
|
360
|
-
* <div>
|
|
361
|
-
* <div>当前值为:{state()}</div>
|
|
362
|
-
* <div>
|
|
363
|
-
* <button type="button" onClick={() => {
|
|
364
|
-
* // 当点击时更新状态
|
|
365
|
-
* state.set(state() + 1)
|
|
366
|
-
* }
|
|
367
|
-
* }>updateState</button>
|
|
368
|
-
* </div>
|
|
369
|
-
* </div>
|
|
370
|
-
* }
|
|
371
|
-
* }
|
|
372
|
-
*/
|
|
373
|
-
function useSignal(state) {
|
|
374
|
-
const usedComponents = new Set();
|
|
375
|
-
function signal() {
|
|
376
|
-
const component = getRendingContext();
|
|
377
|
-
const derivedContext = getDerivedContext();
|
|
378
|
-
if (derivedContext) {
|
|
379
|
-
derivedContext.push(signal);
|
|
380
|
-
}
|
|
381
|
-
if (component && !usedComponents.has(component)) {
|
|
382
|
-
usedComponents.add(component);
|
|
383
|
-
component.destroyCallbacks.push(() => {
|
|
384
|
-
usedComponents.delete(component);
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
return state;
|
|
388
|
-
}
|
|
389
|
-
signal.set = function (newState) {
|
|
390
|
-
if (newState === state) {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
state = newState;
|
|
394
|
-
for (const component of usedComponents) {
|
|
395
|
-
component.markAsDirtied();
|
|
396
|
-
}
|
|
397
|
-
for (const fn of signal[depsKey]) {
|
|
398
|
-
fn();
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
signal[depsKey] = new Set();
|
|
402
|
-
return signal;
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
406
|
-
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
407
|
-
*
|
|
408
|
-
* @param callback
|
|
409
|
-
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
410
|
-
*/
|
|
411
|
-
function useDerived(callback, isContinue) {
|
|
412
|
-
const deps = [];
|
|
413
|
-
derivedStack.push(deps);
|
|
414
|
-
const data = callback();
|
|
415
|
-
derivedStack.pop();
|
|
416
|
-
const signal = useSignal(data);
|
|
417
|
-
if (deps.length) {
|
|
418
|
-
const unListen = useEffect(deps, () => {
|
|
419
|
-
const data = callback();
|
|
420
|
-
signal.set(data);
|
|
421
|
-
if (typeof isContinue === 'function' && !isContinue(data)) {
|
|
422
|
-
unListen();
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
return signal;
|
|
427
|
-
}
|
|
428
|
-
/* eslint-enable max-len*/
|
|
429
|
-
function useEffect(deps, effect) {
|
|
430
|
-
if (typeof deps === 'function' &&
|
|
431
|
-
typeof deps.set === 'undefined' &&
|
|
432
|
-
typeof deps[depsKey] === 'undefined') {
|
|
433
|
-
deps = useDerived(deps);
|
|
434
|
-
}
|
|
435
|
-
const signals = Array.isArray(deps) ? deps : [deps];
|
|
436
|
-
let oldValues = signals.map(s => s());
|
|
437
|
-
let prevCleanup;
|
|
438
|
-
function effectCallback() {
|
|
439
|
-
if (typeof prevCleanup === 'function') {
|
|
440
|
-
prevCleanup();
|
|
441
|
-
}
|
|
442
|
-
const newValues = signals.map(s => s());
|
|
443
|
-
prevCleanup = Array.isArray(deps) ? effect(newValues, oldValues) : effect(newValues[0], oldValues[0]);
|
|
444
|
-
oldValues = newValues;
|
|
445
|
-
}
|
|
446
|
-
for (const dep of signals) {
|
|
447
|
-
dep[depsKey].add(effectCallback);
|
|
448
|
-
}
|
|
449
|
-
const component = getSetupContext(false);
|
|
450
|
-
let isClean = false;
|
|
451
|
-
const destroyFn = () => {
|
|
452
|
-
if (isClean) {
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
isClean = true;
|
|
456
|
-
if (component) {
|
|
457
|
-
const index = component.destroyCallbacks.indexOf(destroyFn);
|
|
458
|
-
component.destroyCallbacks.splice(index, 1);
|
|
459
|
-
}
|
|
460
|
-
for (const dep of signals) {
|
|
461
|
-
dep[depsKey].delete(effectCallback);
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
|
-
if (component) {
|
|
465
|
-
component.destroyCallbacks.push(destroyFn);
|
|
466
|
-
}
|
|
467
|
-
return destroyFn;
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* 通过 IoC 容器当前组件提供上下文共享数据的方法
|
|
471
|
-
* @param provider
|
|
472
|
-
*/
|
|
473
|
-
function provide(provider) {
|
|
474
|
-
const component = getSetupContext();
|
|
475
|
-
component.addProvide(provider);
|
|
476
|
-
return component;
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
480
|
-
*/
|
|
481
|
-
function inject(token, notFoundValue, flags) {
|
|
482
|
-
const component = getSetupContext();
|
|
483
|
-
return component.parentInjector.get(token, notFoundValue, flags);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const jsxErrorFn = makeError('JSX');
|
|
487
|
-
const Fragment = function Fragment() {
|
|
488
|
-
throw jsxErrorFn('Fragment does not support calling.');
|
|
489
|
-
};
|
|
490
|
-
function jsx(setup, config, key) {
|
|
491
|
-
if (typeof setup === 'string') {
|
|
492
|
-
return new JSXElement(setup, config, key);
|
|
493
|
-
}
|
|
494
|
-
return new JSXComponent(function (context) {
|
|
495
|
-
return new Component(context, setup, config, key);
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
function jsxs(setup, config, key) {
|
|
499
|
-
if (typeof setup === 'string') {
|
|
500
|
-
return new JSXElement(setup, config, key);
|
|
501
|
-
}
|
|
502
|
-
return new JSXComponent(function (context) {
|
|
503
|
-
return new Component(context, setup, config, key);
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
class JSXText {
|
|
507
|
-
constructor(text) {
|
|
508
|
-
this.text = text;
|
|
509
|
-
this.$$typeOf = '#text';
|
|
510
|
-
}
|
|
511
|
-
is(target) {
|
|
512
|
-
return target.$$typeOf === this.$$typeOf;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
class JSXElement {
|
|
516
|
-
constructor(name, props, key) {
|
|
517
|
-
this.name = name;
|
|
518
|
-
this.props = props;
|
|
519
|
-
this.key = key;
|
|
520
|
-
this.$$typeOf = this.name;
|
|
521
|
-
}
|
|
522
|
-
is(target) {
|
|
523
|
-
return target.$$typeOf === this.$$typeOf;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
529
|
-
*/
|
|
530
|
-
class RootComponent extends Component {
|
|
531
|
-
constructor(factory, parentInjector = new di.NullInjector()) {
|
|
532
|
-
super(parentInjector, factory, {});
|
|
533
|
-
this.changeEmitter = new stream.Subject();
|
|
534
|
-
}
|
|
535
|
-
markAsChanged() {
|
|
536
|
-
this._changed = true;
|
|
537
|
-
this.changeEmitter.next();
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
const refKey = 'ref';
|
|
542
|
-
function getObjectChanges(newProps, oldProps) {
|
|
543
|
-
const changes = {
|
|
544
|
-
remove: [],
|
|
545
|
-
add: [],
|
|
546
|
-
replace: []
|
|
547
|
-
};
|
|
548
|
-
if (!newProps) {
|
|
549
|
-
if (oldProps) {
|
|
550
|
-
Object.keys(oldProps).forEach(key => {
|
|
551
|
-
changes.remove.push([key, oldProps[key]]);
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
return changes;
|
|
555
|
-
}
|
|
556
|
-
if (!oldProps) {
|
|
557
|
-
Object.keys(newProps).forEach(key => {
|
|
558
|
-
changes.add.push([key, newProps[key]]);
|
|
559
|
-
});
|
|
560
|
-
return changes;
|
|
561
|
-
}
|
|
562
|
-
Object.keys(newProps).forEach(key => {
|
|
563
|
-
const leftValue = newProps[key];
|
|
564
|
-
const rightValue = oldProps[key];
|
|
565
|
-
if (Reflect.has(oldProps, key)) {
|
|
566
|
-
if (leftValue !== rightValue) {
|
|
567
|
-
changes.replace.push([key, leftValue, rightValue]);
|
|
568
|
-
}
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
changes.add.push([key, leftValue]);
|
|
572
|
-
});
|
|
573
|
-
Object.keys(oldProps).forEach(key => {
|
|
574
|
-
if (!Reflect.has(newProps, key)) {
|
|
575
|
-
changes.remove.push([key, oldProps[key]]);
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
return changes;
|
|
579
|
-
}
|
|
580
|
-
function classToString(config) {
|
|
581
|
-
if (!config) {
|
|
582
|
-
return '';
|
|
583
|
-
}
|
|
584
|
-
if (typeof config === 'string') {
|
|
585
|
-
return config;
|
|
586
|
-
}
|
|
587
|
-
else if (Array.isArray(config)) {
|
|
588
|
-
return config.map(i => {
|
|
589
|
-
return classToString(i);
|
|
590
|
-
}).join(' ');
|
|
591
|
-
}
|
|
592
|
-
else if (typeof config === 'object') {
|
|
593
|
-
if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
|
|
594
|
-
return config.toString();
|
|
595
|
-
}
|
|
596
|
-
const classes = [];
|
|
597
|
-
for (const key in config) {
|
|
598
|
-
if ({}.hasOwnProperty.call(config, key) && config[key]) {
|
|
599
|
-
classes.push(key);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
return classes.join(' ');
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
function styleToObject(style) {
|
|
606
|
-
if (typeof style !== 'string') {
|
|
607
|
-
return style;
|
|
608
|
-
}
|
|
609
|
-
const obj = {};
|
|
610
|
-
style.split(';').map(s => s.split(':')).forEach(v => {
|
|
611
|
-
if (!v[0] || !v[1]) {
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
obj[v[0].trim()] = v[1].trim();
|
|
615
|
-
});
|
|
616
|
-
return obj;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
class RootComponentRef {
|
|
620
|
-
}
|
|
621
|
-
class Atom {
|
|
622
|
-
constructor(jsxNode, parent) {
|
|
623
|
-
this.jsxNode = jsxNode;
|
|
624
|
-
this.parent = parent;
|
|
625
|
-
this.nativeNode = null;
|
|
626
|
-
this.child = null;
|
|
627
|
-
this.sibling = null;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
exports.Renderer = class Renderer {
|
|
631
|
-
constructor(nativeRenderer, rootComponentRef) {
|
|
632
|
-
this.nativeRenderer = nativeRenderer;
|
|
633
|
-
this.rootComponentRef = rootComponentRef;
|
|
634
|
-
this.componentAtomCaches = new WeakMap();
|
|
635
|
-
}
|
|
636
|
-
render() {
|
|
637
|
-
const { component, host } = this.rootComponentRef;
|
|
638
|
-
const atom = new Atom(component, null);
|
|
639
|
-
this.buildView(atom, {
|
|
640
|
-
isParent: true,
|
|
641
|
-
host
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
refresh() {
|
|
645
|
-
const { component, host } = this.rootComponentRef;
|
|
646
|
-
this.reconcile(component, {
|
|
647
|
-
host,
|
|
648
|
-
isParent: true
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
reconcile(component, context) {
|
|
652
|
-
if (component.dirty) {
|
|
653
|
-
this.applyChanges(component, context);
|
|
654
|
-
}
|
|
655
|
-
else if (component.changed) {
|
|
656
|
-
const atom = this.componentAtomCaches.get(component).atom.child;
|
|
657
|
-
this.reconcileElement(atom, context);
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
const prevSibling = this.getPrevSibling(component);
|
|
661
|
-
if (prevSibling) {
|
|
662
|
-
context.isParent = false;
|
|
663
|
-
context.host = prevSibling;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
getPrevSibling(component) {
|
|
668
|
-
let atom = this.componentAtomCaches.get(component).atom.child;
|
|
669
|
-
const childAtoms = [];
|
|
670
|
-
while (atom) {
|
|
671
|
-
childAtoms.push(atom);
|
|
672
|
-
atom = atom.sibling;
|
|
673
|
-
}
|
|
674
|
-
const components = [];
|
|
675
|
-
while (childAtoms.length) {
|
|
676
|
-
const last = childAtoms.pop();
|
|
677
|
-
if (last.jsxNode instanceof Component) {
|
|
678
|
-
components.push(last.jsxNode);
|
|
679
|
-
continue;
|
|
680
|
-
}
|
|
681
|
-
return last.nativeNode;
|
|
682
|
-
}
|
|
683
|
-
for (const component of components) {
|
|
684
|
-
const nativeNode = this.getPrevSibling(component);
|
|
685
|
-
if (nativeNode) {
|
|
686
|
-
return nativeNode;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
return null;
|
|
690
|
-
}
|
|
691
|
-
reconcileElement(atom, context) {
|
|
692
|
-
while (atom) {
|
|
693
|
-
if (atom.jsxNode instanceof Component) {
|
|
694
|
-
this.reconcile(atom.jsxNode, context);
|
|
695
|
-
atom = atom.sibling;
|
|
696
|
-
continue;
|
|
697
|
-
}
|
|
698
|
-
if (atom.jsxNode instanceof JSXElement) {
|
|
699
|
-
this.reconcileElement(atom.child, {
|
|
700
|
-
host: atom.nativeNode,
|
|
701
|
-
isParent: true
|
|
702
|
-
});
|
|
703
|
-
context.host = atom.nativeNode;
|
|
704
|
-
context.isParent = false;
|
|
705
|
-
}
|
|
706
|
-
atom = atom.sibling;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
applyChanges(component, context) {
|
|
710
|
-
const { atom, render } = this.componentAtomCaches.get(component);
|
|
711
|
-
const diffAtom = atom.child;
|
|
712
|
-
const template = render();
|
|
713
|
-
if (template) {
|
|
714
|
-
this.linkTemplate(template, component, atom);
|
|
715
|
-
}
|
|
716
|
-
else {
|
|
717
|
-
atom.child = null;
|
|
718
|
-
}
|
|
719
|
-
this.diff(atom.child, diffAtom, context, 0, 0);
|
|
720
|
-
component.rendered();
|
|
721
|
-
}
|
|
722
|
-
diff(newAtom, oldAtom, context, expectIndex, index) {
|
|
723
|
-
const oldChildren = [];
|
|
724
|
-
while (oldAtom) {
|
|
725
|
-
oldChildren.push({
|
|
726
|
-
index,
|
|
727
|
-
atom: oldAtom
|
|
728
|
-
});
|
|
729
|
-
oldAtom = oldAtom.sibling;
|
|
730
|
-
index++;
|
|
731
|
-
}
|
|
732
|
-
const commits = [];
|
|
733
|
-
const changeCommits = {
|
|
734
|
-
reuseComponent: (start, reusedAtom, expectIndex, diffIndex) => {
|
|
735
|
-
commits.push(() => {
|
|
736
|
-
const { add, remove, replace } = getObjectChanges(start.jsxNode.props, reusedAtom.jsxNode.props);
|
|
737
|
-
if (add.length || remove.length || replace.length) {
|
|
738
|
-
reusedAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.props);
|
|
739
|
-
}
|
|
740
|
-
const newProps = start.jsxNode.props;
|
|
741
|
-
start.jsxNode = reusedAtom.jsxNode;
|
|
742
|
-
start.jsxNode.props = newProps;
|
|
743
|
-
const { render } = this.componentAtomCaches.get(start.jsxNode);
|
|
744
|
-
const template = render();
|
|
745
|
-
if (template) {
|
|
746
|
-
this.linkTemplate(template, start.jsxNode, start);
|
|
747
|
-
}
|
|
748
|
-
this.componentAtomCaches.set(start.jsxNode, {
|
|
749
|
-
render,
|
|
750
|
-
atom: start
|
|
751
|
-
});
|
|
752
|
-
if (start.child) {
|
|
753
|
-
this.diff(start.child, reusedAtom.child, context, expectIndex, diffIndex);
|
|
754
|
-
}
|
|
755
|
-
else if (reusedAtom.child) {
|
|
756
|
-
let atom = reusedAtom.child;
|
|
757
|
-
while (atom) {
|
|
758
|
-
this.cleanView(atom, false);
|
|
759
|
-
atom = atom.sibling;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
start.jsxNode.rendered();
|
|
763
|
-
});
|
|
764
|
-
},
|
|
765
|
-
reuseElement: (newAtom, oldAtom, expectIndex, oldIndex) => {
|
|
766
|
-
commits.push((offset) => {
|
|
767
|
-
newAtom.nativeNode = oldAtom.nativeNode;
|
|
768
|
-
const host = context.host;
|
|
769
|
-
if (expectIndex !== oldIndex - offset) {
|
|
770
|
-
if (context.isParent) {
|
|
771
|
-
this.nativeRenderer.prependChild(host, newAtom.nativeNode);
|
|
772
|
-
}
|
|
773
|
-
else {
|
|
774
|
-
this.nativeRenderer.insertAfter(newAtom.nativeNode, host);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
context.host = newAtom.nativeNode;
|
|
778
|
-
context.isParent = false;
|
|
779
|
-
const applyRefs = this.updateNativeNodeProperties(newAtom.jsxNode, oldAtom.jsxNode, newAtom.nativeNode);
|
|
780
|
-
if (newAtom.child) {
|
|
781
|
-
this.diff(newAtom.child, oldAtom.child, {
|
|
782
|
-
host: newAtom.nativeNode,
|
|
783
|
-
isParent: true
|
|
784
|
-
}, 0, 0);
|
|
785
|
-
}
|
|
786
|
-
else if (oldAtom.child) {
|
|
787
|
-
let atom = oldAtom.child;
|
|
788
|
-
while (atom) {
|
|
789
|
-
this.cleanView(atom, false);
|
|
790
|
-
atom = atom.sibling;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
applyRefs();
|
|
794
|
-
});
|
|
795
|
-
},
|
|
796
|
-
reuseText: (newAtom, oldAtom) => {
|
|
797
|
-
commits.push(() => {
|
|
798
|
-
const nativeNode = oldAtom.nativeNode;
|
|
799
|
-
if (newAtom.jsxNode.text !== oldAtom.jsxNode.text) {
|
|
800
|
-
this.nativeRenderer.syncTextContent(nativeNode, newAtom.jsxNode.text);
|
|
801
|
-
}
|
|
802
|
-
newAtom.nativeNode = nativeNode;
|
|
803
|
-
context.host = nativeNode;
|
|
804
|
-
context.isParent = false;
|
|
805
|
-
});
|
|
806
|
-
},
|
|
807
|
-
create: (start) => {
|
|
808
|
-
commits.push(() => {
|
|
809
|
-
this.buildView(start, context);
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
};
|
|
813
|
-
while (newAtom) {
|
|
814
|
-
this.createChanges(newAtom, expectIndex, oldChildren, changeCommits);
|
|
815
|
-
newAtom = newAtom.sibling;
|
|
816
|
-
expectIndex++;
|
|
817
|
-
}
|
|
818
|
-
for (const item of oldChildren) {
|
|
819
|
-
this.cleanView(item.atom, false);
|
|
820
|
-
}
|
|
821
|
-
let j = 0;
|
|
822
|
-
let offset = 0;
|
|
823
|
-
const len = oldChildren.length;
|
|
824
|
-
for (let i = 0; i < commits.length; i++) {
|
|
825
|
-
const commit = commits[i];
|
|
826
|
-
while (j < len) {
|
|
827
|
-
const current = oldChildren[j];
|
|
828
|
-
if (current.index <= i) {
|
|
829
|
-
offset++;
|
|
830
|
-
j++;
|
|
831
|
-
continue;
|
|
832
|
-
}
|
|
833
|
-
break;
|
|
834
|
-
}
|
|
835
|
-
commit(offset);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
createChanges(newAtom, expectIndex, oldChildren, changeCommits) {
|
|
839
|
-
for (let i = 0; i < oldChildren.length; i++) {
|
|
840
|
-
const { atom: diffAtom, index: diffIndex } = oldChildren[i];
|
|
841
|
-
const key = newAtom.jsxNode.key;
|
|
842
|
-
const diffKey = diffAtom.jsxNode.key;
|
|
843
|
-
if (key !== undefined && diffKey !== undefined) {
|
|
844
|
-
if (diffKey !== key) {
|
|
845
|
-
continue;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (newAtom.jsxNode.is(diffAtom.jsxNode)) {
|
|
849
|
-
if (newAtom.jsxNode instanceof JSXElement) {
|
|
850
|
-
changeCommits.reuseElement(newAtom, diffAtom, expectIndex, diffIndex);
|
|
851
|
-
}
|
|
852
|
-
else if (newAtom.jsxNode instanceof JSXText) {
|
|
853
|
-
changeCommits.reuseText(newAtom, diffAtom);
|
|
854
|
-
}
|
|
855
|
-
else {
|
|
856
|
-
changeCommits.reuseComponent(newAtom, diffAtom, expectIndex, diffIndex);
|
|
857
|
-
}
|
|
858
|
-
oldChildren.splice(i, 1);
|
|
859
|
-
return;
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
changeCommits.create(newAtom);
|
|
863
|
-
}
|
|
864
|
-
cleanView(atom, isClean) {
|
|
865
|
-
if (atom.nativeNode) {
|
|
866
|
-
if (!isClean) {
|
|
867
|
-
this.nativeRenderer.remove(atom.nativeNode);
|
|
868
|
-
isClean = true;
|
|
869
|
-
}
|
|
870
|
-
if (atom.jsxNode instanceof JSXElement) {
|
|
871
|
-
const ref = atom.jsxNode.props[refKey];
|
|
872
|
-
this.applyRefs(ref, atom.nativeNode, false);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
let child = atom.child;
|
|
876
|
-
while (child) {
|
|
877
|
-
this.cleanView(child, isClean);
|
|
878
|
-
child = child.sibling;
|
|
879
|
-
}
|
|
880
|
-
if (atom.jsxNode instanceof Component) {
|
|
881
|
-
atom.jsxNode.destroy();
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
buildView(atom, context) {
|
|
885
|
-
if (atom.jsxNode instanceof Component) {
|
|
886
|
-
this.componentRender(atom.jsxNode, atom);
|
|
887
|
-
let child = atom.child;
|
|
888
|
-
while (child) {
|
|
889
|
-
this.buildView(child, context);
|
|
890
|
-
child = child.sibling;
|
|
891
|
-
}
|
|
892
|
-
atom.jsxNode.rendered();
|
|
893
|
-
}
|
|
894
|
-
else {
|
|
895
|
-
let nativeNode;
|
|
896
|
-
let applyRefs = null;
|
|
897
|
-
if (atom.jsxNode instanceof JSXElement) {
|
|
898
|
-
const { nativeNode: n, applyRefs: a } = this.createElement(atom.jsxNode);
|
|
899
|
-
nativeNode = n;
|
|
900
|
-
applyRefs = a;
|
|
901
|
-
}
|
|
902
|
-
else {
|
|
903
|
-
nativeNode = this.createTextNode(atom.jsxNode);
|
|
904
|
-
}
|
|
905
|
-
atom.nativeNode = nativeNode;
|
|
906
|
-
if (context.isParent) {
|
|
907
|
-
this.nativeRenderer.prependChild(context.host, nativeNode);
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
this.nativeRenderer.insertAfter(nativeNode, context.host);
|
|
911
|
-
}
|
|
912
|
-
if (atom.jsxNode instanceof JSXElement) {
|
|
913
|
-
const childContext = {
|
|
914
|
-
isParent: true,
|
|
915
|
-
host: nativeNode
|
|
916
|
-
};
|
|
917
|
-
let child = atom.child;
|
|
918
|
-
while (child) {
|
|
919
|
-
this.buildView(child, childContext);
|
|
920
|
-
child = child.sibling;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
context.host = nativeNode;
|
|
924
|
-
context.isParent = false;
|
|
925
|
-
if (applyRefs) {
|
|
926
|
-
applyRefs();
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
componentRender(component, from) {
|
|
931
|
-
const { template, render } = component.init();
|
|
932
|
-
if (template) {
|
|
933
|
-
this.linkTemplate(template, component, from);
|
|
934
|
-
}
|
|
935
|
-
this.componentAtomCaches.set(component, {
|
|
936
|
-
render,
|
|
937
|
-
atom: from
|
|
938
|
-
});
|
|
939
|
-
return from;
|
|
940
|
-
}
|
|
941
|
-
createChainByComponentFactory(context, factory, parent) {
|
|
942
|
-
const component = factory.createInstance(context);
|
|
943
|
-
if (component.setup === Fragment) {
|
|
944
|
-
return this.createChainByChildren(component, component.props.children, parent);
|
|
945
|
-
}
|
|
946
|
-
return new Atom(component, parent);
|
|
947
|
-
}
|
|
948
|
-
createChainByJSXElement(context, element, parent) {
|
|
949
|
-
const atom = new Atom(element, parent);
|
|
950
|
-
if (Reflect.has(element.props, 'children')) {
|
|
951
|
-
const jsxChildren = element.props.children;
|
|
952
|
-
const children = this.createChainByChildren(context, Array.isArray(jsxChildren) ? jsxChildren : [jsxChildren], atom);
|
|
953
|
-
this.link(atom, children);
|
|
954
|
-
}
|
|
955
|
-
return atom;
|
|
956
|
-
}
|
|
957
|
-
createChainByJSXText(node, parent) {
|
|
958
|
-
return new Atom(node, parent);
|
|
959
|
-
}
|
|
960
|
-
createChainByChildren(context, children, parent) {
|
|
961
|
-
const atoms = [];
|
|
962
|
-
for (const item of children) {
|
|
963
|
-
if (item instanceof JSXElement) {
|
|
964
|
-
atoms.push(this.createChainByJSXElement(context, item, parent));
|
|
965
|
-
continue;
|
|
966
|
-
}
|
|
967
|
-
if (item instanceof JSXComponent) {
|
|
968
|
-
const childAtom = this.createChainByComponentFactory(context, item, parent);
|
|
969
|
-
if (Array.isArray(childAtom)) {
|
|
970
|
-
atoms.push(...childAtom);
|
|
971
|
-
}
|
|
972
|
-
else {
|
|
973
|
-
atoms.push(childAtom);
|
|
974
|
-
}
|
|
975
|
-
continue;
|
|
976
|
-
}
|
|
977
|
-
if (typeof item === 'string' && item.length) {
|
|
978
|
-
atoms.push(this.createChainByJSXText(new JSXText(item), parent));
|
|
979
|
-
continue;
|
|
980
|
-
}
|
|
981
|
-
if (Array.isArray(item)) {
|
|
982
|
-
atoms.push(...this.createChainByChildren(context, item, parent));
|
|
983
|
-
continue;
|
|
984
|
-
}
|
|
985
|
-
if (item !== null && typeof item !== 'undefined') {
|
|
986
|
-
atoms.push(this.createChainByJSXText(new JSXText(String(item)), parent));
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
return atoms;
|
|
990
|
-
}
|
|
991
|
-
linkTemplate(template, component, parent) {
|
|
992
|
-
if (template) {
|
|
993
|
-
const child = template instanceof JSXElement ?
|
|
994
|
-
this.createChainByJSXElement(component, template, parent) :
|
|
995
|
-
this.createChainByComponentFactory(component, template, parent);
|
|
996
|
-
this.link(parent, Array.isArray(child) ? child : [child]);
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
link(parent, children) {
|
|
1000
|
-
for (let i = 1; i < children.length; i++) {
|
|
1001
|
-
const prev = children[i - 1];
|
|
1002
|
-
prev.sibling = children[i];
|
|
1003
|
-
}
|
|
1004
|
-
parent.child = children[0] || null;
|
|
1005
|
-
}
|
|
1006
|
-
createElement(vNode) {
|
|
1007
|
-
const nativeNode = this.nativeRenderer.createElement(vNode.name);
|
|
1008
|
-
const props = vNode.props;
|
|
1009
|
-
let bindingRefs;
|
|
1010
|
-
const keys = Object.keys(props);
|
|
1011
|
-
for (const key of keys) {
|
|
1012
|
-
if (key === 'children') {
|
|
1013
|
-
continue;
|
|
1014
|
-
}
|
|
1015
|
-
if (key === 'class') {
|
|
1016
|
-
this.nativeRenderer.setClass(nativeNode, classToString(props[key]));
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
if (key === 'style') {
|
|
1020
|
-
const style = styleToObject(props.style);
|
|
1021
|
-
Object.keys(style).forEach(key => {
|
|
1022
|
-
this.nativeRenderer.setStyle(nativeNode, key, style[key]);
|
|
1023
|
-
});
|
|
1024
|
-
continue;
|
|
1025
|
-
}
|
|
1026
|
-
if (/^on[A-Z]/.test(key)) {
|
|
1027
|
-
const listener = props[key];
|
|
1028
|
-
if (typeof listener === 'function') {
|
|
1029
|
-
this.nativeRenderer.listen(nativeNode, key.replace(/^on/, '').toLowerCase(), listener);
|
|
1030
|
-
}
|
|
1031
|
-
continue;
|
|
1032
|
-
}
|
|
1033
|
-
if (key === refKey) {
|
|
1034
|
-
bindingRefs = props[key];
|
|
1035
|
-
continue;
|
|
1036
|
-
}
|
|
1037
|
-
this.nativeRenderer.setProperty(nativeNode, key, props[key]);
|
|
1038
|
-
}
|
|
1039
|
-
return {
|
|
1040
|
-
nativeNode,
|
|
1041
|
-
applyRefs: () => {
|
|
1042
|
-
this.applyRefs(bindingRefs, nativeNode, true);
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
}
|
|
1046
|
-
createTextNode(child) {
|
|
1047
|
-
return this.nativeRenderer.createTextNode(child.text);
|
|
1048
|
-
}
|
|
1049
|
-
updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
|
|
1050
|
-
const changes = getObjectChanges(newVNode.props, oldVNode.props);
|
|
1051
|
-
let unBindRefs;
|
|
1052
|
-
let bindRefs;
|
|
1053
|
-
for (const [key, value] of changes.remove) {
|
|
1054
|
-
if (key === 'children') {
|
|
1055
|
-
continue;
|
|
1056
|
-
}
|
|
1057
|
-
if (key === 'class') {
|
|
1058
|
-
this.nativeRenderer.setClass(nativeNode, '');
|
|
1059
|
-
continue;
|
|
1060
|
-
}
|
|
1061
|
-
if (key === 'style') {
|
|
1062
|
-
Object.keys(styleToObject(value)).forEach(styleName => {
|
|
1063
|
-
this.nativeRenderer.removeStyle(nativeNode, styleName);
|
|
1064
|
-
});
|
|
1065
|
-
continue;
|
|
1066
|
-
}
|
|
1067
|
-
if (/^on[A-Z]/.test(key)) {
|
|
1068
|
-
if (typeof value === 'function') {
|
|
1069
|
-
this.nativeRenderer.unListen(nativeNode, key.replace(/^on/, '').toLowerCase(), value);
|
|
1070
|
-
}
|
|
1071
|
-
continue;
|
|
1072
|
-
}
|
|
1073
|
-
if (key === refKey) {
|
|
1074
|
-
unBindRefs = value;
|
|
1075
|
-
continue;
|
|
1076
|
-
}
|
|
1077
|
-
this.nativeRenderer.removeProperty(nativeNode, key);
|
|
1078
|
-
}
|
|
1079
|
-
for (const [key, newValue, oldValue] of changes.replace) {
|
|
1080
|
-
if (key === 'children') {
|
|
1081
|
-
continue;
|
|
1082
|
-
}
|
|
1083
|
-
if (key === 'class') {
|
|
1084
|
-
const oldClassName = classToString(oldValue);
|
|
1085
|
-
const newClassName = classToString(newValue);
|
|
1086
|
-
if (oldClassName !== newClassName) {
|
|
1087
|
-
this.nativeRenderer.setClass(nativeNode, newClassName);
|
|
1088
|
-
}
|
|
1089
|
-
continue;
|
|
1090
|
-
}
|
|
1091
|
-
if (key === 'style') {
|
|
1092
|
-
const styleChanges = getObjectChanges(styleToObject(newValue), styleToObject(oldValue));
|
|
1093
|
-
for (const [styleName] of styleChanges.remove) {
|
|
1094
|
-
this.nativeRenderer.removeStyle(nativeNode, styleName);
|
|
1095
|
-
}
|
|
1096
|
-
for (const [styleName, styleValue] of [...styleChanges.add, ...styleChanges.replace]) {
|
|
1097
|
-
this.nativeRenderer.setStyle(nativeNode, styleName, styleValue);
|
|
1098
|
-
}
|
|
1099
|
-
continue;
|
|
1100
|
-
}
|
|
1101
|
-
if (/^on[A-Z]/.test(key)) {
|
|
1102
|
-
const listenType = key.replace(/^on/, '').toLowerCase();
|
|
1103
|
-
if (typeof oldValue === 'function') {
|
|
1104
|
-
this.nativeRenderer.unListen(nativeNode, listenType, oldValue);
|
|
1105
|
-
}
|
|
1106
|
-
if (typeof newValue === 'function') {
|
|
1107
|
-
this.nativeRenderer.listen(nativeNode, listenType, newValue);
|
|
1108
|
-
}
|
|
1109
|
-
continue;
|
|
1110
|
-
}
|
|
1111
|
-
if (key === refKey) {
|
|
1112
|
-
unBindRefs = oldValue;
|
|
1113
|
-
bindRefs = newValue;
|
|
1114
|
-
continue;
|
|
1115
|
-
}
|
|
1116
|
-
this.nativeRenderer.setProperty(nativeNode, key, newValue);
|
|
1117
|
-
}
|
|
1118
|
-
for (const [key, value] of changes.add) {
|
|
1119
|
-
if (key === 'children') {
|
|
1120
|
-
continue;
|
|
1121
|
-
}
|
|
1122
|
-
if (key === 'class') {
|
|
1123
|
-
this.nativeRenderer.setClass(nativeNode, classToString(value));
|
|
1124
|
-
continue;
|
|
1125
|
-
}
|
|
1126
|
-
if (key === 'style') {
|
|
1127
|
-
const styleObj = styleToObject(value);
|
|
1128
|
-
Object.keys(styleObj).forEach(styleName => {
|
|
1129
|
-
this.nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName]);
|
|
1130
|
-
});
|
|
1131
|
-
continue;
|
|
1132
|
-
}
|
|
1133
|
-
if (/^on[A-Z]/.test(key)) {
|
|
1134
|
-
if (typeof value === 'function') {
|
|
1135
|
-
this.nativeRenderer.listen(nativeNode, key.replace(/^on/, '').toLowerCase(), value);
|
|
1136
|
-
}
|
|
1137
|
-
continue;
|
|
1138
|
-
}
|
|
1139
|
-
if (key === refKey) {
|
|
1140
|
-
bindRefs = value;
|
|
1141
|
-
continue;
|
|
1142
|
-
}
|
|
1143
|
-
this.nativeRenderer.setProperty(nativeNode, key, value);
|
|
1144
|
-
}
|
|
1145
|
-
return () => {
|
|
1146
|
-
this.applyRefs(unBindRefs, nativeNode, false);
|
|
1147
|
-
this.applyRefs(bindRefs, nativeNode, true);
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
applyRefs(refs, nativeNode, binding) {
|
|
1151
|
-
const refList = Array.isArray(refs) ? refs : [refs];
|
|
1152
|
-
for (const item of refList) {
|
|
1153
|
-
if (item instanceof Ref) {
|
|
1154
|
-
binding ? item.bind(nativeNode) : item.unBind(nativeNode);
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
};
|
|
1159
|
-
exports.Renderer = __decorate([
|
|
1160
|
-
di.Injectable(),
|
|
1161
|
-
__metadata("design:paramtypes", [NativeRenderer,
|
|
1162
|
-
RootComponentRef])
|
|
1163
|
-
], exports.Renderer);
|
|
1164
|
-
|
|
1165
|
-
const viewflyErrorFn = makeError('Viewfly');
|
|
1166
|
-
/**
|
|
1167
|
-
* Viewfly 核心类,用于启动一个 Viewfly 应用
|
|
1168
|
-
*/
|
|
1169
|
-
class Viewfly extends di.ReflectiveInjector {
|
|
1170
|
-
constructor(config) {
|
|
1171
|
-
super(new di.NullInjector(), [
|
|
1172
|
-
...(config.providers || []),
|
|
1173
|
-
exports.Renderer,
|
|
1174
|
-
{
|
|
1175
|
-
provide: RootComponentRef,
|
|
1176
|
-
useFactory: () => {
|
|
1177
|
-
return {
|
|
1178
|
-
component: this.rootComponent
|
|
1179
|
-
};
|
|
1180
|
-
}
|
|
1181
|
-
},
|
|
1182
|
-
{
|
|
1183
|
-
provide: NativeRenderer,
|
|
1184
|
-
useFactory() {
|
|
1185
|
-
throw viewflyErrorFn('You must implement the `NativeRenderer` interface to start Viewfly!');
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
]);
|
|
1189
|
-
this.config = config;
|
|
1190
|
-
this.destroyed = false;
|
|
1191
|
-
this.subscription = new stream.Subscription();
|
|
1192
|
-
this.rootComponent = this.createRootComponent(config.root);
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* 启动 Viewfly
|
|
1196
|
-
* @param host 应用根节点
|
|
1197
|
-
*/
|
|
1198
|
-
mount(host) {
|
|
1199
|
-
const rootComponentRef = this.get(RootComponentRef);
|
|
1200
|
-
rootComponentRef.host = host;
|
|
1201
|
-
const renderer = this.get(exports.Renderer);
|
|
1202
|
-
renderer.render();
|
|
1203
|
-
if (this.config.autoUpdate === false) {
|
|
1204
|
-
return;
|
|
1205
|
-
}
|
|
1206
|
-
this.subscription.add(this.rootComponent.changeEmitter.pipe(stream.microTask()).subscribe(() => {
|
|
1207
|
-
renderer.refresh();
|
|
1208
|
-
}));
|
|
1209
|
-
}
|
|
1210
|
-
/**
|
|
1211
|
-
* 销毁 Viewfly 实例
|
|
1212
|
-
*/
|
|
1213
|
-
destroy() {
|
|
1214
|
-
const renderer = this.get(exports.Renderer);
|
|
1215
|
-
this.destroyed = true;
|
|
1216
|
-
this.rootComponent.markAsDirtied();
|
|
1217
|
-
this.subscription.unsubscribe();
|
|
1218
|
-
renderer.refresh();
|
|
1219
|
-
}
|
|
1220
|
-
createRootComponent(rootNode) {
|
|
1221
|
-
return new RootComponent(() => {
|
|
1222
|
-
return () => {
|
|
1223
|
-
return this.destroyed ? null : rootNode;
|
|
1224
|
-
};
|
|
1225
|
-
}, this.config.context);
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
exports.Component = Component;
|
|
1230
|
-
exports.Fragment = Fragment;
|
|
1231
|
-
exports.JSXComponent = JSXComponent;
|
|
1232
|
-
exports.JSXElement = JSXElement;
|
|
1233
|
-
exports.JSXText = JSXText;
|
|
1234
|
-
exports.NativeRenderer = NativeRenderer;
|
|
1235
|
-
exports.Ref = Ref;
|
|
1236
|
-
exports.RootComponent = RootComponent;
|
|
1237
|
-
exports.RootComponentRef = RootComponentRef;
|
|
1238
|
-
exports.Viewfly = Viewfly;
|
|
1239
|
-
exports.inject = inject;
|
|
1240
|
-
exports.jsx = jsx;
|
|
1241
|
-
exports.jsxs = jsxs;
|
|
1242
|
-
exports.makeError = makeError;
|
|
1243
|
-
exports.onDestroy = onDestroy;
|
|
1244
|
-
exports.onMounted = onMounted;
|
|
1245
|
-
exports.onPropsChanged = onPropsChanged;
|
|
1246
|
-
exports.onUpdated = onUpdated;
|
|
1247
|
-
exports.provide = provide;
|
|
1248
|
-
exports.useDerived = useDerived;
|
|
1249
|
-
exports.useEffect = useEffect;
|
|
1250
|
-
exports.useRef = useRef;
|
|
1251
|
-
exports.useSignal = useSignal;
|
|
1252
|
-
Object.keys(di).forEach(function (k) {
|
|
1253
|
-
if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
|
|
1254
|
-
enumerable: true,
|
|
1255
|
-
get: function () { return di[k]; }
|
|
1256
|
-
});
|
|
1257
|
-
});
|