@viewfly/core 0.0.1-alpha.0 → 0.0.1-alpha.2

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.
@@ -30,4 +30,5 @@ export declare class Renderer {
30
30
  private createElement;
31
31
  private createTextNode;
32
32
  private updateNativeNodeProperties;
33
+ private applyRefs;
33
34
  }
@@ -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 Fragment(props) {
38
- return () => new JSXFragment(props);
39
- }
40
- class JSXFragment {
41
- constructor(props) {
42
- this.props = props;
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,12 +71,15 @@ class JSXText {
66
71
  function flatChildren(jsxNodes) {
67
72
  const children = [];
68
73
  for (const node of jsxNodes) {
69
- if (node instanceof JSXElement || typeof node === 'function') {
74
+ if (node instanceof JSXElement || node instanceof JSXComponent) {
70
75
  children.push(node);
71
76
  }
72
77
  else if (typeof node === 'string' && node.length) {
73
78
  children.push(new JSXText(node));
74
79
  }
80
+ else if (Array.isArray(node)) {
81
+ children.push(...flatChildren(node));
82
+ }
75
83
  else if (node !== null && typeof node !== 'undefined') {
76
84
  children.push(new JSXText(String(node)));
77
85
  }
@@ -170,24 +178,24 @@ class JSXElement {
170
178
  }
171
179
  }
172
180
 
173
- function makeError(name) {
174
- return function viewflyError(message) {
175
- const error = new Error(message);
176
- error.name = `[ViewflyError: ${name}]`;
177
- error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
178
- return error;
179
- };
180
- }
181
-
182
- const componentStack = [];
181
+ const componentSetupStack = [];
182
+ const componentRendingStack = [];
183
183
  const componentErrorFn = makeError('component');
184
- function getComponentContext(need = true) {
185
- const current = componentStack[componentStack.length - 1];
184
+ function getSetupContext(need = true) {
185
+ const current = componentSetupStack[componentSetupStack.length - 1];
186
186
  if (!current && need) {
187
187
  throw componentErrorFn('cannot be called outside the component!');
188
188
  }
189
189
  return current;
190
190
  }
191
+ function getRendingContext() {
192
+ return componentRendingStack[componentRendingStack.length - 1];
193
+ }
194
+ class JSXComponent {
195
+ constructor(createInstance) {
196
+ this.createInstance = createInstance;
197
+ }
198
+ }
191
199
  /**
192
200
  * Viewfly 组件管理类,用于管理组件的生命周期,上下文等
193
201
  */
@@ -221,7 +229,6 @@ class Component extends ReflectiveInjector {
221
229
  });
222
230
  }
223
231
  init() {
224
- componentStack.push(this);
225
232
  const self = this;
226
233
  const props = new Proxy({}, {
227
234
  get(_, key) {
@@ -233,15 +240,18 @@ class Component extends ReflectiveInjector {
233
240
  throw componentErrorFn('component props is readonly!');
234
241
  }
235
242
  });
243
+ componentSetupStack.push(this);
236
244
  const render = this.setup(props);
245
+ componentSetupStack.pop();
246
+ componentRendingStack.push(this);
237
247
  const template = render();
238
- componentStack.pop();
248
+ componentRendingStack.pop();
239
249
  return {
240
250
  template,
241
251
  render: () => {
242
- componentStack.push(this);
252
+ componentRendingStack.push(this);
243
253
  const template = render();
244
- componentStack.pop();
254
+ componentRendingStack.pop();
245
255
  return template;
246
256
  }
247
257
  };
@@ -330,7 +340,7 @@ class Component extends ReflectiveInjector {
330
340
  * ```
331
341
  */
332
342
  function onMount(callback) {
333
- const component = getComponentContext();
343
+ const component = getSetupContext();
334
344
  component.mountCallbacks.push(callback);
335
345
  }
336
346
  /**
@@ -349,7 +359,7 @@ function onMount(callback) {
349
359
  * ```
350
360
  */
351
361
  function onUpdated(callback) {
352
- const component = getComponentContext();
362
+ const component = getSetupContext();
353
363
  component.updatedCallbacks.push(callback);
354
364
  return () => {
355
365
  const index = component.updatedCallbacks.indexOf(callback);
@@ -378,7 +388,7 @@ function onUpdated(callback) {
378
388
  * ```
379
389
  */
380
390
  function onPropsChanged(callback) {
381
- const component = getComponentContext();
391
+ const component = getSetupContext();
382
392
  component.propsChangedCallbacks.push(callback);
383
393
  return () => {
384
394
  const index = component.propsChangedCallbacks.indexOf(callback);
@@ -392,31 +402,33 @@ function onPropsChanged(callback) {
392
402
  * @param callback
393
403
  */
394
404
  function onDestroy(callback) {
395
- const component = getComponentContext();
405
+ const component = getSetupContext();
396
406
  component.destroyCallbacks.push(callback);
397
407
  }
398
408
  class Ref {
399
- // private prevValue: T | null = null
400
- constructor(callback, component) {
409
+ constructor(callback) {
401
410
  this.callback = callback;
402
- this.component = component;
403
- this.unListenFn = null;
404
- component.destroyCallbacks.push(() => {
405
- this.unListen();
406
- });
411
+ this.unBindMap = new WeakMap;
412
+ this.targetCaches = new Set();
407
413
  }
408
- update(value) {
409
- // if (value === this.prevValue) {
410
- // return
411
- // }
412
- // this.prevValue = value
413
- this.unListen();
414
- this.unListenFn = this.callback(value) || null;
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
+ }
415
426
  }
416
- unListen() {
417
- if (typeof this.unListenFn === 'function') {
418
- this.unListenFn();
419
- this.unListenFn = null;
427
+ unBind(value) {
428
+ this.targetCaches.delete(value);
429
+ const unBindFn = this.unBindMap.get(value);
430
+ if (typeof unBindFn === 'function') {
431
+ unBindFn();
420
432
  }
421
433
  }
422
434
  }
@@ -442,8 +454,7 @@ class Ref {
442
454
  * ```
443
455
  */
444
456
  function useRef(callback) {
445
- const component = getComponentContext();
446
- return new Ref(callback, component);
457
+ return new Ref(callback);
447
458
  }
448
459
  const depsKey = Symbol('deps');
449
460
  /**
@@ -472,7 +483,7 @@ const depsKey = Symbol('deps');
472
483
  function useSignal(state) {
473
484
  const usedComponents = new Set();
474
485
  function stateManager() {
475
- const component = getComponentContext(false);
486
+ const component = getRendingContext();
476
487
  if (component && !usedComponents.has(component)) {
477
488
  usedComponents.add(component);
478
489
  component.destroyCallbacks.push(() => {
@@ -482,10 +493,7 @@ function useSignal(state) {
482
493
  return state;
483
494
  }
484
495
  stateManager.set = function (newState) {
485
- if (typeof newState === 'function') {
486
- newState = newState(state);
487
- }
488
- else if (newState === state) {
496
+ if (newState === state) {
489
497
  return;
490
498
  }
491
499
  state = newState;
@@ -518,7 +526,7 @@ function useEffect(deps, effect) {
518
526
  for (const dep of signals) {
519
527
  dep[depsKey].add(effectCallback);
520
528
  }
521
- const component = getComponentContext(false);
529
+ const component = getSetupContext(false);
522
530
  let isClean = false;
523
531
  const destroyFn = () => {
524
532
  if (isClean) {
@@ -543,7 +551,7 @@ function useEffect(deps, effect) {
543
551
  * @param provider
544
552
  */
545
553
  function provide(provider) {
546
- const component = getComponentContext();
554
+ const component = getSetupContext();
547
555
  component.addProvide(provider);
548
556
  return component;
549
557
  }
@@ -551,7 +559,7 @@ function provide(provider) {
551
559
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
552
560
  */
553
561
  function inject(token, notFoundValue, flags) {
554
- const component = getComponentContext();
562
+ const component = getSetupContext();
555
563
  return component.parentInjector.get(token, notFoundValue, flags);
556
564
  }
557
565
 
@@ -856,9 +864,7 @@ let Renderer = class Renderer {
856
864
  }
857
865
  if (atom.jsxNode instanceof JSXElement) {
858
866
  const ref = atom.jsxNode.props.attrs.get(refKey);
859
- if (ref instanceof Ref) {
860
- ref.unListen();
861
- }
867
+ this.applyRefs(ref, atom.nativeNode, false);
862
868
  }
863
869
  }
864
870
  let child = atom.child;
@@ -1012,7 +1018,7 @@ let Renderer = class Renderer {
1012
1018
  return parent;
1013
1019
  }
1014
1020
  createChainByComponentFactory(context, factory, parent) {
1015
- const component = factory(context);
1021
+ const component = factory.createInstance(context);
1016
1022
  if (component.setup === Fragment) {
1017
1023
  return this.createChainByChildren(component, component.props.children, parent);
1018
1024
  }
@@ -1066,9 +1072,10 @@ let Renderer = class Renderer {
1066
1072
  const nativeNode = this.nativeRenderer.createElement(vNode.name);
1067
1073
  const props = vNode.props;
1068
1074
  if (props) {
1075
+ let bindingRefs;
1069
1076
  props.attrs.forEach((value, key) => {
1070
- if (key === refKey && value instanceof Ref) {
1071
- value.update(nativeNode);
1077
+ if (key === refKey) {
1078
+ bindingRefs = value;
1072
1079
  return;
1073
1080
  }
1074
1081
  this.nativeRenderer.setProperty(nativeNode, key, value);
@@ -1080,6 +1087,7 @@ let Renderer = class Renderer {
1080
1087
  Object.keys(props.listeners).forEach(type => {
1081
1088
  this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1082
1089
  });
1090
+ this.applyRefs(bindingRefs, nativeNode, true);
1083
1091
  }
1084
1092
  return nativeNode;
1085
1093
  }
@@ -1093,16 +1101,18 @@ let Renderer = class Renderer {
1093
1101
  }
1094
1102
  styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1095
1103
  styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
1104
+ let unBindRefs;
1096
1105
  attrChanges.remove.forEach(([key, value]) => {
1097
- if (key === refKey && value instanceof Ref) {
1098
- value.unListen();
1106
+ if (key === refKey) {
1107
+ unBindRefs = value;
1099
1108
  return;
1100
1109
  }
1101
1110
  this.nativeRenderer.removeProperty(nativeNode, key);
1102
1111
  });
1112
+ let bindRefs;
1103
1113
  attrChanges.set.forEach(([key, value]) => {
1104
- if (key === refKey && value instanceof Ref) {
1105
- value.update(nativeNode);
1114
+ if (key === refKey) {
1115
+ bindRefs = value;
1106
1116
  return;
1107
1117
  }
1108
1118
  this.nativeRenderer.setProperty(nativeNode, key, value);
@@ -1115,6 +1125,16 @@ let Renderer = class Renderer {
1115
1125
  listenerChanges.add.forEach(i => {
1116
1126
  this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1117
1127
  });
1128
+ this.applyRefs(unBindRefs, nativeNode, false);
1129
+ this.applyRefs(bindRefs, nativeNode, true);
1130
+ }
1131
+ applyRefs(refs, nativeNode, binding) {
1132
+ refs = Array.isArray(refs) ? refs : [refs];
1133
+ for (const item of refs) {
1134
+ if (item instanceof Ref) {
1135
+ binding ? item.bind(nativeNode) : item.unBind(nativeNode);
1136
+ }
1137
+ }
1118
1138
  }
1119
1139
  };
1120
1140
  Renderer = __decorate([
@@ -1185,4 +1205,4 @@ class Viewfly extends ReflectiveInjector {
1185
1205
  }
1186
1206
  }
1187
1207
 
1188
- export { Component, Fragment, JSXElement, JSXFragment, JSXText, NativeRenderer, Props, Ref, Renderer, RootComponent, RootComponentRef, Viewfly, inject, jsx, jsxs, onDestroy, onMount, onPropsChanged, onUpdated, provide, useEffect, useRef, useSignal };
1208
+ 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 Fragment(props) {
39
- return () => new JSXFragment(props);
40
- }
41
- class JSXFragment {
42
- constructor(props) {
43
- this.props = props;
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,12 +72,15 @@ class JSXText {
67
72
  function flatChildren(jsxNodes) {
68
73
  const children = [];
69
74
  for (const node of jsxNodes) {
70
- if (node instanceof JSXElement || typeof node === 'function') {
75
+ if (node instanceof JSXElement || node instanceof JSXComponent) {
71
76
  children.push(node);
72
77
  }
73
78
  else if (typeof node === 'string' && node.length) {
74
79
  children.push(new JSXText(node));
75
80
  }
81
+ else if (Array.isArray(node)) {
82
+ children.push(...flatChildren(node));
83
+ }
76
84
  else if (node !== null && typeof node !== 'undefined') {
77
85
  children.push(new JSXText(String(node)));
78
86
  }
@@ -171,24 +179,24 @@ class JSXElement {
171
179
  }
172
180
  }
173
181
 
174
- function makeError(name) {
175
- return function viewflyError(message) {
176
- const error = new Error(message);
177
- error.name = `[ViewflyError: ${name}]`;
178
- error.stack = error.stack.replace(/\n.*?(?=\n)/, '');
179
- return error;
180
- };
181
- }
182
-
183
- const componentStack = [];
182
+ const componentSetupStack = [];
183
+ const componentRendingStack = [];
184
184
  const componentErrorFn = makeError('component');
185
- function getComponentContext(need = true) {
186
- const current = componentStack[componentStack.length - 1];
185
+ function getSetupContext(need = true) {
186
+ const current = componentSetupStack[componentSetupStack.length - 1];
187
187
  if (!current && need) {
188
188
  throw componentErrorFn('cannot be called outside the component!');
189
189
  }
190
190
  return current;
191
191
  }
192
+ function getRendingContext() {
193
+ return componentRendingStack[componentRendingStack.length - 1];
194
+ }
195
+ class JSXComponent {
196
+ constructor(createInstance) {
197
+ this.createInstance = createInstance;
198
+ }
199
+ }
192
200
  /**
193
201
  * Viewfly 组件管理类,用于管理组件的生命周期,上下文等
194
202
  */
@@ -222,7 +230,6 @@ class Component extends di.ReflectiveInjector {
222
230
  });
223
231
  }
224
232
  init() {
225
- componentStack.push(this);
226
233
  const self = this;
227
234
  const props = new Proxy({}, {
228
235
  get(_, key) {
@@ -234,15 +241,18 @@ class Component extends di.ReflectiveInjector {
234
241
  throw componentErrorFn('component props is readonly!');
235
242
  }
236
243
  });
244
+ componentSetupStack.push(this);
237
245
  const render = this.setup(props);
246
+ componentSetupStack.pop();
247
+ componentRendingStack.push(this);
238
248
  const template = render();
239
- componentStack.pop();
249
+ componentRendingStack.pop();
240
250
  return {
241
251
  template,
242
252
  render: () => {
243
- componentStack.push(this);
253
+ componentRendingStack.push(this);
244
254
  const template = render();
245
- componentStack.pop();
255
+ componentRendingStack.pop();
246
256
  return template;
247
257
  }
248
258
  };
@@ -331,7 +341,7 @@ class Component extends di.ReflectiveInjector {
331
341
  * ```
332
342
  */
333
343
  function onMount(callback) {
334
- const component = getComponentContext();
344
+ const component = getSetupContext();
335
345
  component.mountCallbacks.push(callback);
336
346
  }
337
347
  /**
@@ -350,7 +360,7 @@ function onMount(callback) {
350
360
  * ```
351
361
  */
352
362
  function onUpdated(callback) {
353
- const component = getComponentContext();
363
+ const component = getSetupContext();
354
364
  component.updatedCallbacks.push(callback);
355
365
  return () => {
356
366
  const index = component.updatedCallbacks.indexOf(callback);
@@ -379,7 +389,7 @@ function onUpdated(callback) {
379
389
  * ```
380
390
  */
381
391
  function onPropsChanged(callback) {
382
- const component = getComponentContext();
392
+ const component = getSetupContext();
383
393
  component.propsChangedCallbacks.push(callback);
384
394
  return () => {
385
395
  const index = component.propsChangedCallbacks.indexOf(callback);
@@ -393,31 +403,33 @@ function onPropsChanged(callback) {
393
403
  * @param callback
394
404
  */
395
405
  function onDestroy(callback) {
396
- const component = getComponentContext();
406
+ const component = getSetupContext();
397
407
  component.destroyCallbacks.push(callback);
398
408
  }
399
409
  class Ref {
400
- // private prevValue: T | null = null
401
- constructor(callback, component) {
410
+ constructor(callback) {
402
411
  this.callback = callback;
403
- this.component = component;
404
- this.unListenFn = null;
405
- component.destroyCallbacks.push(() => {
406
- this.unListen();
407
- });
412
+ this.unBindMap = new WeakMap;
413
+ this.targetCaches = new Set();
408
414
  }
409
- update(value) {
410
- // if (value === this.prevValue) {
411
- // return
412
- // }
413
- // this.prevValue = value
414
- this.unListen();
415
- this.unListenFn = this.callback(value) || null;
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
+ }
416
427
  }
417
- unListen() {
418
- if (typeof this.unListenFn === 'function') {
419
- this.unListenFn();
420
- this.unListenFn = null;
428
+ unBind(value) {
429
+ this.targetCaches.delete(value);
430
+ const unBindFn = this.unBindMap.get(value);
431
+ if (typeof unBindFn === 'function') {
432
+ unBindFn();
421
433
  }
422
434
  }
423
435
  }
@@ -443,8 +455,7 @@ class Ref {
443
455
  * ```
444
456
  */
445
457
  function useRef(callback) {
446
- const component = getComponentContext();
447
- return new Ref(callback, component);
458
+ return new Ref(callback);
448
459
  }
449
460
  const depsKey = Symbol('deps');
450
461
  /**
@@ -473,7 +484,7 @@ const depsKey = Symbol('deps');
473
484
  function useSignal(state) {
474
485
  const usedComponents = new Set();
475
486
  function stateManager() {
476
- const component = getComponentContext(false);
487
+ const component = getRendingContext();
477
488
  if (component && !usedComponents.has(component)) {
478
489
  usedComponents.add(component);
479
490
  component.destroyCallbacks.push(() => {
@@ -483,10 +494,7 @@ function useSignal(state) {
483
494
  return state;
484
495
  }
485
496
  stateManager.set = function (newState) {
486
- if (typeof newState === 'function') {
487
- newState = newState(state);
488
- }
489
- else if (newState === state) {
497
+ if (newState === state) {
490
498
  return;
491
499
  }
492
500
  state = newState;
@@ -519,7 +527,7 @@ function useEffect(deps, effect) {
519
527
  for (const dep of signals) {
520
528
  dep[depsKey].add(effectCallback);
521
529
  }
522
- const component = getComponentContext(false);
530
+ const component = getSetupContext(false);
523
531
  let isClean = false;
524
532
  const destroyFn = () => {
525
533
  if (isClean) {
@@ -544,7 +552,7 @@ function useEffect(deps, effect) {
544
552
  * @param provider
545
553
  */
546
554
  function provide(provider) {
547
- const component = getComponentContext();
555
+ const component = getSetupContext();
548
556
  component.addProvide(provider);
549
557
  return component;
550
558
  }
@@ -552,7 +560,7 @@ function provide(provider) {
552
560
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
553
561
  */
554
562
  function inject(token, notFoundValue, flags) {
555
- const component = getComponentContext();
563
+ const component = getSetupContext();
556
564
  return component.parentInjector.get(token, notFoundValue, flags);
557
565
  }
558
566
 
@@ -857,9 +865,7 @@ exports.Renderer = class Renderer {
857
865
  }
858
866
  if (atom.jsxNode instanceof JSXElement) {
859
867
  const ref = atom.jsxNode.props.attrs.get(refKey);
860
- if (ref instanceof Ref) {
861
- ref.unListen();
862
- }
868
+ this.applyRefs(ref, atom.nativeNode, false);
863
869
  }
864
870
  }
865
871
  let child = atom.child;
@@ -1013,7 +1019,7 @@ exports.Renderer = class Renderer {
1013
1019
  return parent;
1014
1020
  }
1015
1021
  createChainByComponentFactory(context, factory, parent) {
1016
- const component = factory(context);
1022
+ const component = factory.createInstance(context);
1017
1023
  if (component.setup === Fragment) {
1018
1024
  return this.createChainByChildren(component, component.props.children, parent);
1019
1025
  }
@@ -1067,9 +1073,10 @@ exports.Renderer = class Renderer {
1067
1073
  const nativeNode = this.nativeRenderer.createElement(vNode.name);
1068
1074
  const props = vNode.props;
1069
1075
  if (props) {
1076
+ let bindingRefs;
1070
1077
  props.attrs.forEach((value, key) => {
1071
- if (key === refKey && value instanceof Ref) {
1072
- value.update(nativeNode);
1078
+ if (key === refKey) {
1079
+ bindingRefs = value;
1073
1080
  return;
1074
1081
  }
1075
1082
  this.nativeRenderer.setProperty(nativeNode, key, value);
@@ -1081,6 +1088,7 @@ exports.Renderer = class Renderer {
1081
1088
  Object.keys(props.listeners).forEach(type => {
1082
1089
  this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1083
1090
  });
1091
+ this.applyRefs(bindingRefs, nativeNode, true);
1084
1092
  }
1085
1093
  return nativeNode;
1086
1094
  }
@@ -1094,16 +1102,18 @@ exports.Renderer = class Renderer {
1094
1102
  }
1095
1103
  styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1096
1104
  styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
1105
+ let unBindRefs;
1097
1106
  attrChanges.remove.forEach(([key, value]) => {
1098
- if (key === refKey && value instanceof Ref) {
1099
- value.unListen();
1107
+ if (key === refKey) {
1108
+ unBindRefs = value;
1100
1109
  return;
1101
1110
  }
1102
1111
  this.nativeRenderer.removeProperty(nativeNode, key);
1103
1112
  });
1113
+ let bindRefs;
1104
1114
  attrChanges.set.forEach(([key, value]) => {
1105
- if (key === refKey && value instanceof Ref) {
1106
- value.update(nativeNode);
1115
+ if (key === refKey) {
1116
+ bindRefs = value;
1107
1117
  return;
1108
1118
  }
1109
1119
  this.nativeRenderer.setProperty(nativeNode, key, value);
@@ -1116,6 +1126,16 @@ exports.Renderer = class Renderer {
1116
1126
  listenerChanges.add.forEach(i => {
1117
1127
  this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1118
1128
  });
1129
+ this.applyRefs(unBindRefs, nativeNode, false);
1130
+ this.applyRefs(bindRefs, nativeNode, true);
1131
+ }
1132
+ applyRefs(refs, nativeNode, binding) {
1133
+ refs = Array.isArray(refs) ? refs : [refs];
1134
+ for (const item of refs) {
1135
+ if (item instanceof Ref) {
1136
+ binding ? item.bind(nativeNode) : item.unBind(nativeNode);
1137
+ }
1138
+ }
1119
1139
  }
1120
1140
  };
1121
1141
  exports.Renderer = __decorate([
@@ -1188,8 +1208,8 @@ class Viewfly extends di.ReflectiveInjector {
1188
1208
 
1189
1209
  exports.Component = Component;
1190
1210
  exports.Fragment = Fragment;
1211
+ exports.JSXComponent = JSXComponent;
1191
1212
  exports.JSXElement = JSXElement;
1192
- exports.JSXFragment = JSXFragment;
1193
1213
  exports.JSXText = JSXText;
1194
1214
  exports.NativeRenderer = NativeRenderer;
1195
1215
  exports.Props = Props;
@@ -1,9 +1,10 @@
1
1
  import { Provider, ReflectiveInjector, AbstractType, Type, InjectionToken, InjectFlags, Injector } from '@tanbo/di';
2
2
  import { JSXProps, JSXElement, Props } from './jsx-element';
3
- export interface ComponentFactory {
4
- (context: Injector): Component;
3
+ export declare class JSXComponent {
4
+ createInstance: (injector: Component) => Component;
5
+ constructor(createInstance: (injector: Component) => Component);
5
6
  }
6
- export type JSXTemplate = JSXElement | ComponentFactory | null | void;
7
+ export type JSXTemplate = JSXElement | JSXComponent | null | void;
7
8
  export interface ComponentSetup {
8
9
  (props: JSXProps<any>): () => JSXTemplate;
9
10
  }
@@ -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 component;
109
- private unListenFn;
110
- constructor(callback: RefListener<T>, component: Component);
111
- update(value: T): void;
112
- unListen(): void;
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 | ((oldState: T) => T)): void;
151
+ set(newState: T): void;
151
152
  [depsKey]: Set<LifeCycleCallback>;
152
153
  }
153
154
  /**
@@ -1,19 +1,15 @@
1
- import { ComponentFactory, ComponentSetup } from './component';
2
- export type JSXChildNode = JSXElement | ComponentFactory | string | number | boolean | null | undefined;
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 function Fragment(props: Props | null): () => JSXFragment;
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): ComponentFactory;
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): ComponentFactory;
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 | ComponentFactory | JSXText;
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>;
@@ -1,7 +1,7 @@
1
1
  import { Provider, ReflectiveInjector } from '@tanbo/di';
2
2
  import { NativeNode } from './foundation/_api';
3
- import { ComponentFactory, JSXElement } from './model/_api';
4
- export type RootNode = JSXElement | ComponentFactory;
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.0",
3
+ "version": "0.0.1-alpha.2",
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",