@viewfly/core 0.0.1-alpha.1 → 0.0.1-alpha.3
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/bundles/foundation/renderer.d.ts +1 -0
- package/bundles/index.esm.js +92 -73
- package/bundles/index.js +92 -73
- package/bundles/model/component.d.ts +14 -13
- package/bundles/model/jsx-element.d.ts +6 -10
- package/bundles/viewfly.d.ts +2 -2
- package/package.json +4 -3
package/bundles/index.esm.js
CHANGED
|
@@ -34,29 +34,34 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
34
34
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function
|
|
38
|
-
return ()
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
37
|
+
function makeError(name) {
|
|
38
|
+
return function viewflyError(message) {
|
|
39
|
+
const error = new Error(message);
|
|
40
|
+
error.name = `[ViewflyError: ${name}]`;
|
|
41
|
+
error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
|
|
42
|
+
return error;
|
|
43
|
+
};
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
const jsxErrorFn = makeError('JSX');
|
|
47
|
+
const Fragment = function Fragment() {
|
|
48
|
+
throw jsxErrorFn('Fragment does not support calling.');
|
|
49
|
+
};
|
|
45
50
|
function jsx(setup, config) {
|
|
46
51
|
if (typeof setup === 'string') {
|
|
47
52
|
return new JSXElement(setup, config);
|
|
48
53
|
}
|
|
49
|
-
return function (context) {
|
|
54
|
+
return new JSXComponent(function (context) {
|
|
50
55
|
return new Component(context, setup, config);
|
|
51
|
-
};
|
|
56
|
+
});
|
|
52
57
|
}
|
|
53
58
|
function jsxs(setup, config) {
|
|
54
59
|
if (typeof setup === 'string') {
|
|
55
60
|
return new JSXElement(setup, config);
|
|
56
61
|
}
|
|
57
|
-
return function (context) {
|
|
62
|
+
return new JSXComponent(function (context) {
|
|
58
63
|
return new Component(context, setup, config);
|
|
59
|
-
};
|
|
64
|
+
});
|
|
60
65
|
}
|
|
61
66
|
class JSXText {
|
|
62
67
|
constructor(text) {
|
|
@@ -66,7 +71,7 @@ class JSXText {
|
|
|
66
71
|
function flatChildren(jsxNodes) {
|
|
67
72
|
const children = [];
|
|
68
73
|
for (const node of jsxNodes) {
|
|
69
|
-
if (node instanceof JSXElement ||
|
|
74
|
+
if (node instanceof JSXElement || node instanceof JSXComponent) {
|
|
70
75
|
children.push(node);
|
|
71
76
|
}
|
|
72
77
|
else if (typeof node === 'string' && node.length) {
|
|
@@ -173,24 +178,24 @@ class JSXElement {
|
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const error = new Error(message);
|
|
179
|
-
error.name = `[ViewflyError: ${name}]`;
|
|
180
|
-
error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
|
|
181
|
-
return error;
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const componentStack = [];
|
|
181
|
+
const componentSetupStack = [];
|
|
182
|
+
const componentRendingStack = [];
|
|
186
183
|
const componentErrorFn = makeError('component');
|
|
187
|
-
function
|
|
188
|
-
const current =
|
|
184
|
+
function getSetupContext(need = true) {
|
|
185
|
+
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
189
186
|
if (!current && need) {
|
|
190
187
|
throw componentErrorFn('cannot be called outside the component!');
|
|
191
188
|
}
|
|
192
189
|
return current;
|
|
193
190
|
}
|
|
191
|
+
function getRendingContext() {
|
|
192
|
+
return componentRendingStack[componentRendingStack.length - 1];
|
|
193
|
+
}
|
|
194
|
+
class JSXComponent {
|
|
195
|
+
constructor(createInstance) {
|
|
196
|
+
this.createInstance = createInstance;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
194
199
|
/**
|
|
195
200
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
196
201
|
*/
|
|
@@ -224,9 +229,8 @@ class Component extends ReflectiveInjector {
|
|
|
224
229
|
});
|
|
225
230
|
}
|
|
226
231
|
init() {
|
|
227
|
-
componentStack.push(this);
|
|
228
232
|
const self = this;
|
|
229
|
-
const props = new Proxy({}, {
|
|
233
|
+
const props = new Proxy(this.config || {}, {
|
|
230
234
|
get(_, key) {
|
|
231
235
|
if (self.config) {
|
|
232
236
|
return self.config[key];
|
|
@@ -236,15 +240,18 @@ class Component extends ReflectiveInjector {
|
|
|
236
240
|
throw componentErrorFn('component props is readonly!');
|
|
237
241
|
}
|
|
238
242
|
});
|
|
243
|
+
componentSetupStack.push(this);
|
|
239
244
|
const render = this.setup(props);
|
|
245
|
+
componentSetupStack.pop();
|
|
246
|
+
componentRendingStack.push(this);
|
|
240
247
|
const template = render();
|
|
241
|
-
|
|
248
|
+
componentRendingStack.pop();
|
|
242
249
|
return {
|
|
243
250
|
template,
|
|
244
251
|
render: () => {
|
|
245
|
-
|
|
252
|
+
componentRendingStack.push(this);
|
|
246
253
|
const template = render();
|
|
247
|
-
|
|
254
|
+
componentRendingStack.pop();
|
|
248
255
|
return template;
|
|
249
256
|
}
|
|
250
257
|
};
|
|
@@ -333,7 +340,7 @@ class Component extends ReflectiveInjector {
|
|
|
333
340
|
* ```
|
|
334
341
|
*/
|
|
335
342
|
function onMount(callback) {
|
|
336
|
-
const component =
|
|
343
|
+
const component = getSetupContext();
|
|
337
344
|
component.mountCallbacks.push(callback);
|
|
338
345
|
}
|
|
339
346
|
/**
|
|
@@ -352,7 +359,7 @@ function onMount(callback) {
|
|
|
352
359
|
* ```
|
|
353
360
|
*/
|
|
354
361
|
function onUpdated(callback) {
|
|
355
|
-
const component =
|
|
362
|
+
const component = getSetupContext();
|
|
356
363
|
component.updatedCallbacks.push(callback);
|
|
357
364
|
return () => {
|
|
358
365
|
const index = component.updatedCallbacks.indexOf(callback);
|
|
@@ -381,7 +388,7 @@ function onUpdated(callback) {
|
|
|
381
388
|
* ```
|
|
382
389
|
*/
|
|
383
390
|
function onPropsChanged(callback) {
|
|
384
|
-
const component =
|
|
391
|
+
const component = getSetupContext();
|
|
385
392
|
component.propsChangedCallbacks.push(callback);
|
|
386
393
|
return () => {
|
|
387
394
|
const index = component.propsChangedCallbacks.indexOf(callback);
|
|
@@ -395,31 +402,33 @@ function onPropsChanged(callback) {
|
|
|
395
402
|
* @param callback
|
|
396
403
|
*/
|
|
397
404
|
function onDestroy(callback) {
|
|
398
|
-
const component =
|
|
405
|
+
const component = getSetupContext();
|
|
399
406
|
component.destroyCallbacks.push(callback);
|
|
400
407
|
}
|
|
401
408
|
class Ref {
|
|
402
|
-
|
|
403
|
-
constructor(callback, component) {
|
|
409
|
+
constructor(callback) {
|
|
404
410
|
this.callback = callback;
|
|
405
|
-
this.
|
|
406
|
-
this.
|
|
407
|
-
component.destroyCallbacks.push(() => {
|
|
408
|
-
this.unListen();
|
|
409
|
-
});
|
|
411
|
+
this.unBindMap = new WeakMap;
|
|
412
|
+
this.targetCaches = new Set();
|
|
410
413
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
414
|
+
bind(value) {
|
|
415
|
+
if (typeof value !== 'object' || value === null) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (this.targetCaches.has(value)) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.targetCaches.add(value);
|
|
422
|
+
const unBindFn = this.callback(value);
|
|
423
|
+
if (typeof unBindFn === 'function') {
|
|
424
|
+
this.unBindMap.set(value, unBindFn);
|
|
425
|
+
}
|
|
418
426
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
427
|
+
unBind(value) {
|
|
428
|
+
this.targetCaches.delete(value);
|
|
429
|
+
const unBindFn = this.unBindMap.get(value);
|
|
430
|
+
if (typeof unBindFn === 'function') {
|
|
431
|
+
unBindFn();
|
|
423
432
|
}
|
|
424
433
|
}
|
|
425
434
|
}
|
|
@@ -445,8 +454,7 @@ class Ref {
|
|
|
445
454
|
* ```
|
|
446
455
|
*/
|
|
447
456
|
function useRef(callback) {
|
|
448
|
-
|
|
449
|
-
return new Ref(callback, component);
|
|
457
|
+
return new Ref(callback);
|
|
450
458
|
}
|
|
451
459
|
const depsKey = Symbol('deps');
|
|
452
460
|
/**
|
|
@@ -475,7 +483,7 @@ const depsKey = Symbol('deps');
|
|
|
475
483
|
function useSignal(state) {
|
|
476
484
|
const usedComponents = new Set();
|
|
477
485
|
function stateManager() {
|
|
478
|
-
const component =
|
|
486
|
+
const component = getRendingContext();
|
|
479
487
|
if (component && !usedComponents.has(component)) {
|
|
480
488
|
usedComponents.add(component);
|
|
481
489
|
component.destroyCallbacks.push(() => {
|
|
@@ -485,10 +493,7 @@ function useSignal(state) {
|
|
|
485
493
|
return state;
|
|
486
494
|
}
|
|
487
495
|
stateManager.set = function (newState) {
|
|
488
|
-
if (
|
|
489
|
-
newState = newState(state);
|
|
490
|
-
}
|
|
491
|
-
else if (newState === state) {
|
|
496
|
+
if (newState === state) {
|
|
492
497
|
return;
|
|
493
498
|
}
|
|
494
499
|
state = newState;
|
|
@@ -521,7 +526,7 @@ function useEffect(deps, effect) {
|
|
|
521
526
|
for (const dep of signals) {
|
|
522
527
|
dep[depsKey].add(effectCallback);
|
|
523
528
|
}
|
|
524
|
-
const component =
|
|
529
|
+
const component = getSetupContext(false);
|
|
525
530
|
let isClean = false;
|
|
526
531
|
const destroyFn = () => {
|
|
527
532
|
if (isClean) {
|
|
@@ -546,7 +551,7 @@ function useEffect(deps, effect) {
|
|
|
546
551
|
* @param provider
|
|
547
552
|
*/
|
|
548
553
|
function provide(provider) {
|
|
549
|
-
const component =
|
|
554
|
+
const component = getSetupContext();
|
|
550
555
|
component.addProvide(provider);
|
|
551
556
|
return component;
|
|
552
557
|
}
|
|
@@ -554,7 +559,7 @@ function provide(provider) {
|
|
|
554
559
|
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
555
560
|
*/
|
|
556
561
|
function inject(token, notFoundValue, flags) {
|
|
557
|
-
const component =
|
|
562
|
+
const component = getSetupContext();
|
|
558
563
|
return component.parentInjector.get(token, notFoundValue, flags);
|
|
559
564
|
}
|
|
560
565
|
|
|
@@ -563,7 +568,7 @@ function inject(token, notFoundValue, flags) {
|
|
|
563
568
|
*/
|
|
564
569
|
class RootComponent extends Component {
|
|
565
570
|
constructor(factory) {
|
|
566
|
-
super(new NullInjector(), factory,
|
|
571
|
+
super(new NullInjector(), factory, null);
|
|
567
572
|
this.changeEmitter = new Subject();
|
|
568
573
|
}
|
|
569
574
|
markAsChanged() {
|
|
@@ -859,9 +864,7 @@ let Renderer = class Renderer {
|
|
|
859
864
|
}
|
|
860
865
|
if (atom.jsxNode instanceof JSXElement) {
|
|
861
866
|
const ref = atom.jsxNode.props.attrs.get(refKey);
|
|
862
|
-
|
|
863
|
-
ref.unListen();
|
|
864
|
-
}
|
|
867
|
+
this.applyRefs(ref, atom.nativeNode, false);
|
|
865
868
|
}
|
|
866
869
|
}
|
|
867
870
|
let child = atom.child;
|
|
@@ -902,7 +905,9 @@ let Renderer = class Renderer {
|
|
|
902
905
|
if (isChanged) {
|
|
903
906
|
diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
|
|
904
907
|
}
|
|
908
|
+
const newProps = start.jsxNode.props;
|
|
905
909
|
start.jsxNode = diffAtom.jsxNode;
|
|
910
|
+
start.jsxNode.props = newProps;
|
|
906
911
|
const { render } = this.componentAtomCaches.get(start.jsxNode);
|
|
907
912
|
const template = render();
|
|
908
913
|
if (template) {
|
|
@@ -1015,7 +1020,7 @@ let Renderer = class Renderer {
|
|
|
1015
1020
|
return parent;
|
|
1016
1021
|
}
|
|
1017
1022
|
createChainByComponentFactory(context, factory, parent) {
|
|
1018
|
-
const component = factory(context);
|
|
1023
|
+
const component = factory.createInstance(context);
|
|
1019
1024
|
if (component.setup === Fragment) {
|
|
1020
1025
|
return this.createChainByChildren(component, component.props.children, parent);
|
|
1021
1026
|
}
|
|
@@ -1069,9 +1074,10 @@ let Renderer = class Renderer {
|
|
|
1069
1074
|
const nativeNode = this.nativeRenderer.createElement(vNode.name);
|
|
1070
1075
|
const props = vNode.props;
|
|
1071
1076
|
if (props) {
|
|
1077
|
+
let bindingRefs;
|
|
1072
1078
|
props.attrs.forEach((value, key) => {
|
|
1073
|
-
if (key === refKey
|
|
1074
|
-
value
|
|
1079
|
+
if (key === refKey) {
|
|
1080
|
+
bindingRefs = value;
|
|
1075
1081
|
return;
|
|
1076
1082
|
}
|
|
1077
1083
|
this.nativeRenderer.setProperty(nativeNode, key, value);
|
|
@@ -1083,6 +1089,7 @@ let Renderer = class Renderer {
|
|
|
1083
1089
|
Object.keys(props.listeners).forEach(type => {
|
|
1084
1090
|
this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
|
|
1085
1091
|
});
|
|
1092
|
+
this.applyRefs(bindingRefs, nativeNode, true);
|
|
1086
1093
|
}
|
|
1087
1094
|
return nativeNode;
|
|
1088
1095
|
}
|
|
@@ -1096,16 +1103,18 @@ let Renderer = class Renderer {
|
|
|
1096
1103
|
}
|
|
1097
1104
|
styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
|
|
1098
1105
|
styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
|
|
1106
|
+
let unBindRefs;
|
|
1099
1107
|
attrChanges.remove.forEach(([key, value]) => {
|
|
1100
|
-
if (key === refKey
|
|
1101
|
-
value
|
|
1108
|
+
if (key === refKey) {
|
|
1109
|
+
unBindRefs = value;
|
|
1102
1110
|
return;
|
|
1103
1111
|
}
|
|
1104
1112
|
this.nativeRenderer.removeProperty(nativeNode, key);
|
|
1105
1113
|
});
|
|
1114
|
+
let bindRefs;
|
|
1106
1115
|
attrChanges.set.forEach(([key, value]) => {
|
|
1107
|
-
if (key === refKey
|
|
1108
|
-
value
|
|
1116
|
+
if (key === refKey) {
|
|
1117
|
+
bindRefs = value;
|
|
1109
1118
|
return;
|
|
1110
1119
|
}
|
|
1111
1120
|
this.nativeRenderer.setProperty(nativeNode, key, value);
|
|
@@ -1118,6 +1127,16 @@ let Renderer = class Renderer {
|
|
|
1118
1127
|
listenerChanges.add.forEach(i => {
|
|
1119
1128
|
this.nativeRenderer.listen(nativeNode, i[0], i[1]);
|
|
1120
1129
|
});
|
|
1130
|
+
this.applyRefs(unBindRefs, nativeNode, false);
|
|
1131
|
+
this.applyRefs(bindRefs, nativeNode, true);
|
|
1132
|
+
}
|
|
1133
|
+
applyRefs(refs, nativeNode, binding) {
|
|
1134
|
+
refs = Array.isArray(refs) ? refs : [refs];
|
|
1135
|
+
for (const item of refs) {
|
|
1136
|
+
if (item instanceof Ref) {
|
|
1137
|
+
binding ? item.bind(nativeNode) : item.unBind(nativeNode);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1121
1140
|
}
|
|
1122
1141
|
};
|
|
1123
1142
|
Renderer = __decorate([
|
|
@@ -1188,4 +1207,4 @@ class Viewfly extends ReflectiveInjector {
|
|
|
1188
1207
|
}
|
|
1189
1208
|
}
|
|
1190
1209
|
|
|
1191
|
-
export { Component, Fragment,
|
|
1210
|
+
export { Component, Fragment, JSXComponent, JSXElement, JSXText, NativeRenderer, Props, Ref, Renderer, RootComponent, RootComponentRef, Viewfly, inject, jsx, jsxs, onDestroy, onMount, onPropsChanged, onUpdated, provide, useEffect, useRef, useSignal };
|
package/bundles/index.js
CHANGED
|
@@ -35,29 +35,34 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
35
35
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function
|
|
39
|
-
return ()
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
38
|
+
function makeError(name) {
|
|
39
|
+
return function viewflyError(message) {
|
|
40
|
+
const error = new Error(message);
|
|
41
|
+
error.name = `[ViewflyError: ${name}]`;
|
|
42
|
+
error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
|
|
43
|
+
return error;
|
|
44
|
+
};
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
const jsxErrorFn = makeError('JSX');
|
|
48
|
+
const Fragment = function Fragment() {
|
|
49
|
+
throw jsxErrorFn('Fragment does not support calling.');
|
|
50
|
+
};
|
|
46
51
|
function jsx(setup, config) {
|
|
47
52
|
if (typeof setup === 'string') {
|
|
48
53
|
return new JSXElement(setup, config);
|
|
49
54
|
}
|
|
50
|
-
return function (context) {
|
|
55
|
+
return new JSXComponent(function (context) {
|
|
51
56
|
return new Component(context, setup, config);
|
|
52
|
-
};
|
|
57
|
+
});
|
|
53
58
|
}
|
|
54
59
|
function jsxs(setup, config) {
|
|
55
60
|
if (typeof setup === 'string') {
|
|
56
61
|
return new JSXElement(setup, config);
|
|
57
62
|
}
|
|
58
|
-
return function (context) {
|
|
63
|
+
return new JSXComponent(function (context) {
|
|
59
64
|
return new Component(context, setup, config);
|
|
60
|
-
};
|
|
65
|
+
});
|
|
61
66
|
}
|
|
62
67
|
class JSXText {
|
|
63
68
|
constructor(text) {
|
|
@@ -67,7 +72,7 @@ class JSXText {
|
|
|
67
72
|
function flatChildren(jsxNodes) {
|
|
68
73
|
const children = [];
|
|
69
74
|
for (const node of jsxNodes) {
|
|
70
|
-
if (node instanceof JSXElement ||
|
|
75
|
+
if (node instanceof JSXElement || node instanceof JSXComponent) {
|
|
71
76
|
children.push(node);
|
|
72
77
|
}
|
|
73
78
|
else if (typeof node === 'string' && node.length) {
|
|
@@ -174,24 +179,24 @@ class JSXElement {
|
|
|
174
179
|
}
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const error = new Error(message);
|
|
180
|
-
error.name = `[ViewflyError: ${name}]`;
|
|
181
|
-
error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
|
|
182
|
-
return error;
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const componentStack = [];
|
|
182
|
+
const componentSetupStack = [];
|
|
183
|
+
const componentRendingStack = [];
|
|
187
184
|
const componentErrorFn = makeError('component');
|
|
188
|
-
function
|
|
189
|
-
const current =
|
|
185
|
+
function getSetupContext(need = true) {
|
|
186
|
+
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
190
187
|
if (!current && need) {
|
|
191
188
|
throw componentErrorFn('cannot be called outside the component!');
|
|
192
189
|
}
|
|
193
190
|
return current;
|
|
194
191
|
}
|
|
192
|
+
function getRendingContext() {
|
|
193
|
+
return componentRendingStack[componentRendingStack.length - 1];
|
|
194
|
+
}
|
|
195
|
+
class JSXComponent {
|
|
196
|
+
constructor(createInstance) {
|
|
197
|
+
this.createInstance = createInstance;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
195
200
|
/**
|
|
196
201
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
197
202
|
*/
|
|
@@ -225,9 +230,8 @@ class Component extends di.ReflectiveInjector {
|
|
|
225
230
|
});
|
|
226
231
|
}
|
|
227
232
|
init() {
|
|
228
|
-
componentStack.push(this);
|
|
229
233
|
const self = this;
|
|
230
|
-
const props = new Proxy({}, {
|
|
234
|
+
const props = new Proxy(this.config || {}, {
|
|
231
235
|
get(_, key) {
|
|
232
236
|
if (self.config) {
|
|
233
237
|
return self.config[key];
|
|
@@ -237,15 +241,18 @@ class Component extends di.ReflectiveInjector {
|
|
|
237
241
|
throw componentErrorFn('component props is readonly!');
|
|
238
242
|
}
|
|
239
243
|
});
|
|
244
|
+
componentSetupStack.push(this);
|
|
240
245
|
const render = this.setup(props);
|
|
246
|
+
componentSetupStack.pop();
|
|
247
|
+
componentRendingStack.push(this);
|
|
241
248
|
const template = render();
|
|
242
|
-
|
|
249
|
+
componentRendingStack.pop();
|
|
243
250
|
return {
|
|
244
251
|
template,
|
|
245
252
|
render: () => {
|
|
246
|
-
|
|
253
|
+
componentRendingStack.push(this);
|
|
247
254
|
const template = render();
|
|
248
|
-
|
|
255
|
+
componentRendingStack.pop();
|
|
249
256
|
return template;
|
|
250
257
|
}
|
|
251
258
|
};
|
|
@@ -334,7 +341,7 @@ class Component extends di.ReflectiveInjector {
|
|
|
334
341
|
* ```
|
|
335
342
|
*/
|
|
336
343
|
function onMount(callback) {
|
|
337
|
-
const component =
|
|
344
|
+
const component = getSetupContext();
|
|
338
345
|
component.mountCallbacks.push(callback);
|
|
339
346
|
}
|
|
340
347
|
/**
|
|
@@ -353,7 +360,7 @@ function onMount(callback) {
|
|
|
353
360
|
* ```
|
|
354
361
|
*/
|
|
355
362
|
function onUpdated(callback) {
|
|
356
|
-
const component =
|
|
363
|
+
const component = getSetupContext();
|
|
357
364
|
component.updatedCallbacks.push(callback);
|
|
358
365
|
return () => {
|
|
359
366
|
const index = component.updatedCallbacks.indexOf(callback);
|
|
@@ -382,7 +389,7 @@ function onUpdated(callback) {
|
|
|
382
389
|
* ```
|
|
383
390
|
*/
|
|
384
391
|
function onPropsChanged(callback) {
|
|
385
|
-
const component =
|
|
392
|
+
const component = getSetupContext();
|
|
386
393
|
component.propsChangedCallbacks.push(callback);
|
|
387
394
|
return () => {
|
|
388
395
|
const index = component.propsChangedCallbacks.indexOf(callback);
|
|
@@ -396,31 +403,33 @@ function onPropsChanged(callback) {
|
|
|
396
403
|
* @param callback
|
|
397
404
|
*/
|
|
398
405
|
function onDestroy(callback) {
|
|
399
|
-
const component =
|
|
406
|
+
const component = getSetupContext();
|
|
400
407
|
component.destroyCallbacks.push(callback);
|
|
401
408
|
}
|
|
402
409
|
class Ref {
|
|
403
|
-
|
|
404
|
-
constructor(callback, component) {
|
|
410
|
+
constructor(callback) {
|
|
405
411
|
this.callback = callback;
|
|
406
|
-
this.
|
|
407
|
-
this.
|
|
408
|
-
component.destroyCallbacks.push(() => {
|
|
409
|
-
this.unListen();
|
|
410
|
-
});
|
|
412
|
+
this.unBindMap = new WeakMap;
|
|
413
|
+
this.targetCaches = new Set();
|
|
411
414
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
415
|
+
bind(value) {
|
|
416
|
+
if (typeof value !== 'object' || value === null) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (this.targetCaches.has(value)) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
this.targetCaches.add(value);
|
|
423
|
+
const unBindFn = this.callback(value);
|
|
424
|
+
if (typeof unBindFn === 'function') {
|
|
425
|
+
this.unBindMap.set(value, unBindFn);
|
|
426
|
+
}
|
|
419
427
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
428
|
+
unBind(value) {
|
|
429
|
+
this.targetCaches.delete(value);
|
|
430
|
+
const unBindFn = this.unBindMap.get(value);
|
|
431
|
+
if (typeof unBindFn === 'function') {
|
|
432
|
+
unBindFn();
|
|
424
433
|
}
|
|
425
434
|
}
|
|
426
435
|
}
|
|
@@ -446,8 +455,7 @@ class Ref {
|
|
|
446
455
|
* ```
|
|
447
456
|
*/
|
|
448
457
|
function useRef(callback) {
|
|
449
|
-
|
|
450
|
-
return new Ref(callback, component);
|
|
458
|
+
return new Ref(callback);
|
|
451
459
|
}
|
|
452
460
|
const depsKey = Symbol('deps');
|
|
453
461
|
/**
|
|
@@ -476,7 +484,7 @@ const depsKey = Symbol('deps');
|
|
|
476
484
|
function useSignal(state) {
|
|
477
485
|
const usedComponents = new Set();
|
|
478
486
|
function stateManager() {
|
|
479
|
-
const component =
|
|
487
|
+
const component = getRendingContext();
|
|
480
488
|
if (component && !usedComponents.has(component)) {
|
|
481
489
|
usedComponents.add(component);
|
|
482
490
|
component.destroyCallbacks.push(() => {
|
|
@@ -486,10 +494,7 @@ function useSignal(state) {
|
|
|
486
494
|
return state;
|
|
487
495
|
}
|
|
488
496
|
stateManager.set = function (newState) {
|
|
489
|
-
if (
|
|
490
|
-
newState = newState(state);
|
|
491
|
-
}
|
|
492
|
-
else if (newState === state) {
|
|
497
|
+
if (newState === state) {
|
|
493
498
|
return;
|
|
494
499
|
}
|
|
495
500
|
state = newState;
|
|
@@ -522,7 +527,7 @@ function useEffect(deps, effect) {
|
|
|
522
527
|
for (const dep of signals) {
|
|
523
528
|
dep[depsKey].add(effectCallback);
|
|
524
529
|
}
|
|
525
|
-
const component =
|
|
530
|
+
const component = getSetupContext(false);
|
|
526
531
|
let isClean = false;
|
|
527
532
|
const destroyFn = () => {
|
|
528
533
|
if (isClean) {
|
|
@@ -547,7 +552,7 @@ function useEffect(deps, effect) {
|
|
|
547
552
|
* @param provider
|
|
548
553
|
*/
|
|
549
554
|
function provide(provider) {
|
|
550
|
-
const component =
|
|
555
|
+
const component = getSetupContext();
|
|
551
556
|
component.addProvide(provider);
|
|
552
557
|
return component;
|
|
553
558
|
}
|
|
@@ -555,7 +560,7 @@ function provide(provider) {
|
|
|
555
560
|
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
556
561
|
*/
|
|
557
562
|
function inject(token, notFoundValue, flags) {
|
|
558
|
-
const component =
|
|
563
|
+
const component = getSetupContext();
|
|
559
564
|
return component.parentInjector.get(token, notFoundValue, flags);
|
|
560
565
|
}
|
|
561
566
|
|
|
@@ -564,7 +569,7 @@ function inject(token, notFoundValue, flags) {
|
|
|
564
569
|
*/
|
|
565
570
|
class RootComponent extends Component {
|
|
566
571
|
constructor(factory) {
|
|
567
|
-
super(new di.NullInjector(), factory,
|
|
572
|
+
super(new di.NullInjector(), factory, null);
|
|
568
573
|
this.changeEmitter = new stream.Subject();
|
|
569
574
|
}
|
|
570
575
|
markAsChanged() {
|
|
@@ -860,9 +865,7 @@ exports.Renderer = class Renderer {
|
|
|
860
865
|
}
|
|
861
866
|
if (atom.jsxNode instanceof JSXElement) {
|
|
862
867
|
const ref = atom.jsxNode.props.attrs.get(refKey);
|
|
863
|
-
|
|
864
|
-
ref.unListen();
|
|
865
|
-
}
|
|
868
|
+
this.applyRefs(ref, atom.nativeNode, false);
|
|
866
869
|
}
|
|
867
870
|
}
|
|
868
871
|
let child = atom.child;
|
|
@@ -903,7 +906,9 @@ exports.Renderer = class Renderer {
|
|
|
903
906
|
if (isChanged) {
|
|
904
907
|
diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
|
|
905
908
|
}
|
|
909
|
+
const newProps = start.jsxNode.props;
|
|
906
910
|
start.jsxNode = diffAtom.jsxNode;
|
|
911
|
+
start.jsxNode.props = newProps;
|
|
907
912
|
const { render } = this.componentAtomCaches.get(start.jsxNode);
|
|
908
913
|
const template = render();
|
|
909
914
|
if (template) {
|
|
@@ -1016,7 +1021,7 @@ exports.Renderer = class Renderer {
|
|
|
1016
1021
|
return parent;
|
|
1017
1022
|
}
|
|
1018
1023
|
createChainByComponentFactory(context, factory, parent) {
|
|
1019
|
-
const component = factory(context);
|
|
1024
|
+
const component = factory.createInstance(context);
|
|
1020
1025
|
if (component.setup === Fragment) {
|
|
1021
1026
|
return this.createChainByChildren(component, component.props.children, parent);
|
|
1022
1027
|
}
|
|
@@ -1070,9 +1075,10 @@ exports.Renderer = class Renderer {
|
|
|
1070
1075
|
const nativeNode = this.nativeRenderer.createElement(vNode.name);
|
|
1071
1076
|
const props = vNode.props;
|
|
1072
1077
|
if (props) {
|
|
1078
|
+
let bindingRefs;
|
|
1073
1079
|
props.attrs.forEach((value, key) => {
|
|
1074
|
-
if (key === refKey
|
|
1075
|
-
value
|
|
1080
|
+
if (key === refKey) {
|
|
1081
|
+
bindingRefs = value;
|
|
1076
1082
|
return;
|
|
1077
1083
|
}
|
|
1078
1084
|
this.nativeRenderer.setProperty(nativeNode, key, value);
|
|
@@ -1084,6 +1090,7 @@ exports.Renderer = class Renderer {
|
|
|
1084
1090
|
Object.keys(props.listeners).forEach(type => {
|
|
1085
1091
|
this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
|
|
1086
1092
|
});
|
|
1093
|
+
this.applyRefs(bindingRefs, nativeNode, true);
|
|
1087
1094
|
}
|
|
1088
1095
|
return nativeNode;
|
|
1089
1096
|
}
|
|
@@ -1097,16 +1104,18 @@ exports.Renderer = class Renderer {
|
|
|
1097
1104
|
}
|
|
1098
1105
|
styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
|
|
1099
1106
|
styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
|
|
1107
|
+
let unBindRefs;
|
|
1100
1108
|
attrChanges.remove.forEach(([key, value]) => {
|
|
1101
|
-
if (key === refKey
|
|
1102
|
-
value
|
|
1109
|
+
if (key === refKey) {
|
|
1110
|
+
unBindRefs = value;
|
|
1103
1111
|
return;
|
|
1104
1112
|
}
|
|
1105
1113
|
this.nativeRenderer.removeProperty(nativeNode, key);
|
|
1106
1114
|
});
|
|
1115
|
+
let bindRefs;
|
|
1107
1116
|
attrChanges.set.forEach(([key, value]) => {
|
|
1108
|
-
if (key === refKey
|
|
1109
|
-
value
|
|
1117
|
+
if (key === refKey) {
|
|
1118
|
+
bindRefs = value;
|
|
1110
1119
|
return;
|
|
1111
1120
|
}
|
|
1112
1121
|
this.nativeRenderer.setProperty(nativeNode, key, value);
|
|
@@ -1119,6 +1128,16 @@ exports.Renderer = class Renderer {
|
|
|
1119
1128
|
listenerChanges.add.forEach(i => {
|
|
1120
1129
|
this.nativeRenderer.listen(nativeNode, i[0], i[1]);
|
|
1121
1130
|
});
|
|
1131
|
+
this.applyRefs(unBindRefs, nativeNode, false);
|
|
1132
|
+
this.applyRefs(bindRefs, nativeNode, true);
|
|
1133
|
+
}
|
|
1134
|
+
applyRefs(refs, nativeNode, binding) {
|
|
1135
|
+
refs = Array.isArray(refs) ? refs : [refs];
|
|
1136
|
+
for (const item of refs) {
|
|
1137
|
+
if (item instanceof Ref) {
|
|
1138
|
+
binding ? item.bind(nativeNode) : item.unBind(nativeNode);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1122
1141
|
}
|
|
1123
1142
|
};
|
|
1124
1143
|
exports.Renderer = __decorate([
|
|
@@ -1191,8 +1210,8 @@ class Viewfly extends di.ReflectiveInjector {
|
|
|
1191
1210
|
|
|
1192
1211
|
exports.Component = Component;
|
|
1193
1212
|
exports.Fragment = Fragment;
|
|
1213
|
+
exports.JSXComponent = JSXComponent;
|
|
1194
1214
|
exports.JSXElement = JSXElement;
|
|
1195
|
-
exports.JSXFragment = JSXFragment;
|
|
1196
1215
|
exports.JSXText = JSXText;
|
|
1197
1216
|
exports.NativeRenderer = NativeRenderer;
|
|
1198
1217
|
exports.Props = Props;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Provider, ReflectiveInjector, AbstractType, Type, InjectionToken, InjectFlags, Injector } from '@tanbo/di';
|
|
2
2
|
import { JSXProps, JSXElement, Props } from './jsx-element';
|
|
3
|
-
export
|
|
4
|
-
(
|
|
3
|
+
export declare class JSXComponent {
|
|
4
|
+
createInstance: (injector: Component) => Component;
|
|
5
|
+
constructor(createInstance: (injector: Component) => Component);
|
|
5
6
|
}
|
|
6
|
-
export type JSXTemplate = JSXElement |
|
|
7
|
+
export type JSXTemplate = JSXElement | JSXComponent | null | void;
|
|
7
8
|
export interface ComponentSetup {
|
|
8
|
-
(props
|
|
9
|
+
(props?: JSXProps<any>): () => JSXTemplate;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
@@ -103,13 +104,13 @@ export declare function onDestroy(callback: () => void): void;
|
|
|
103
104
|
export interface RefListener<T> {
|
|
104
105
|
(current: T): void | (() => void);
|
|
105
106
|
}
|
|
106
|
-
export declare class Ref<T> {
|
|
107
|
+
export declare class Ref<T extends object> {
|
|
107
108
|
private callback;
|
|
108
|
-
private
|
|
109
|
-
private
|
|
110
|
-
constructor(callback: RefListener<T
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
private unBindMap;
|
|
110
|
+
private targetCaches;
|
|
111
|
+
constructor(callback: RefListener<T>);
|
|
112
|
+
bind(value: T): void;
|
|
113
|
+
unBind(value: T): void;
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
115
116
|
* 用于节点渲染完成时获取 DOM 节点
|
|
@@ -132,7 +133,7 @@ export declare class Ref<T> {
|
|
|
132
133
|
* }
|
|
133
134
|
* ```
|
|
134
135
|
*/
|
|
135
|
-
export declare function useRef<T>(callback: RefListener<T>): Ref<T>;
|
|
136
|
+
export declare function useRef<T extends object>(callback: RefListener<T>): Ref<T>;
|
|
136
137
|
declare const depsKey: unique symbol;
|
|
137
138
|
/**
|
|
138
139
|
* 组件状态实例,直接调用可以获取最新的状态,通过 set 方法可以更新状态
|
|
@@ -144,10 +145,10 @@ export interface Signal<T> {
|
|
|
144
145
|
*/
|
|
145
146
|
(): T;
|
|
146
147
|
/**
|
|
147
|
-
*
|
|
148
|
+
* 更新组件状态的方法,可以传入最新的值
|
|
148
149
|
* @param newState
|
|
149
150
|
*/
|
|
150
|
-
set(newState: T
|
|
151
|
+
set(newState: T): void;
|
|
151
152
|
[depsKey]: Set<LifeCycleCallback>;
|
|
152
153
|
}
|
|
153
154
|
/**
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export type JSXChildNode = JSXElement |
|
|
1
|
+
import { JSXComponent, ComponentSetup } from './component';
|
|
2
|
+
export type JSXChildNode = JSXElement | JSXComponent | string | number | boolean | null | undefined;
|
|
3
3
|
export interface JSXProps<T = JSXChildNode | JSXChildNode[]> {
|
|
4
4
|
children?: T;
|
|
5
5
|
[key: string]: any;
|
|
6
6
|
[key: symbol]: any;
|
|
7
7
|
}
|
|
8
|
-
export declare
|
|
9
|
-
export declare class JSXFragment {
|
|
10
|
-
props: Props | null;
|
|
11
|
-
constructor(props: Props | null);
|
|
12
|
-
}
|
|
8
|
+
export declare const Fragment: () => never;
|
|
13
9
|
export declare function jsx<T extends JSXChildNode>(name: string, config: JSXProps<T> | null): JSXElement;
|
|
14
|
-
export declare function jsx<T extends JSXChildNode>(setup: ComponentSetup, config: JSXProps<T> | null):
|
|
10
|
+
export declare function jsx<T extends JSXChildNode>(setup: ComponentSetup, config: JSXProps<T> | null): JSXComponent;
|
|
15
11
|
export declare function jsxs<T extends JSXChildNode[]>(name: string, config: JSXProps<T> | null): JSXElement;
|
|
16
|
-
export declare function jsxs<T extends JSXChildNode[]>(setup: ComponentSetup, config: JSXProps<T> | null):
|
|
12
|
+
export declare function jsxs<T extends JSXChildNode[]>(setup: ComponentSetup, config: JSXProps<T> | null): JSXComponent;
|
|
17
13
|
export interface VElementListeners {
|
|
18
14
|
[listenKey: string]: <T extends Event>(ev: T) => any;
|
|
19
15
|
}
|
|
@@ -21,7 +17,7 @@ export declare class JSXText {
|
|
|
21
17
|
text: string;
|
|
22
18
|
constructor(text: string);
|
|
23
19
|
}
|
|
24
|
-
export type VNode = JSXElement |
|
|
20
|
+
export type VNode = JSXElement | JSXComponent | JSXText;
|
|
25
21
|
export declare class Props {
|
|
26
22
|
attrs: Map<string, any>;
|
|
27
23
|
styles: Map<string, string | number>;
|
package/bundles/viewfly.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Provider, ReflectiveInjector } from '@tanbo/di';
|
|
2
2
|
import { NativeNode } from './foundation/_api';
|
|
3
|
-
import {
|
|
4
|
-
export type RootNode = JSXElement |
|
|
3
|
+
import { JSXComponent, JSXElement } from './model/_api';
|
|
4
|
+
export type RootNode = JSXElement | JSXComponent;
|
|
5
5
|
/**
|
|
6
6
|
* Viewfly 配置项
|
|
7
7
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viewfly/core",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.3",
|
|
4
4
|
"description": "Viewfly is a simple and easy-to-use JavaScript framework with an intuitive development experience.",
|
|
5
5
|
"main": "./bundles/index.js",
|
|
6
6
|
"module": "./bundles/index.esm.js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"keywords": [],
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@tanbo/di": "^1.1.4",
|
|
19
|
-
"@tanbo/stream": "^1.1.9"
|
|
19
|
+
"@tanbo/stream": "^1.1.9",
|
|
20
|
+
"reflect-metadata": "^0.1.13"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@rollup/plugin-commonjs": "^23.0.2",
|
|
@@ -36,5 +37,5 @@
|
|
|
36
37
|
"bugs": {
|
|
37
38
|
"url": "https://github.com/viewfly/viewfly.git/issues"
|
|
38
39
|
},
|
|
39
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "e0795c315c3b3e1df2e3d2d9f823843b91838ff6"
|
|
40
41
|
}
|