@viewfly/core 0.0.1-alpha.9 → 0.0.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.
package/bundles/index.js CHANGED
@@ -44,175 +44,19 @@ function __metadata(metadataKey, metadataValue) {
44
44
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
45
45
  }
46
46
 
47
- const jsxErrorFn = makeError('JSX');
48
- const Fragment = function Fragment() {
49
- throw jsxErrorFn('Fragment does not support calling.');
50
- };
51
- function jsx(setup, config, key) {
52
- if (typeof setup === 'string') {
53
- return new JSXElement(setup, config, key);
54
- }
55
- return new JSXComponent(function (context) {
56
- return new Component(context, setup, config, key);
57
- });
58
- }
59
- function jsxs(setup, config, key) {
60
- if (typeof setup === 'string') {
61
- return new JSXElement(setup, config, key);
62
- }
63
- return new JSXComponent(function (context) {
64
- return new Component(context, setup, config, key);
65
- });
66
- }
67
- class JSXText {
68
- constructor(text) {
69
- this.text = text;
70
- this.$$typeOf = '#text';
71
- }
72
- is(target) {
73
- return target.$$typeOf === this.$$typeOf;
74
- }
75
- }
76
- class Props {
77
- constructor(props) {
78
- this.attrs = new Map();
79
- this.styles = new Map();
80
- this.classes = '';
81
- this.listeners = {};
82
- this.children = [];
83
- if (!props) {
84
- return;
85
- }
86
- Object.keys(props).forEach(key => {
87
- if (key === 'children') {
88
- if (props.children !== null && typeof props.children !== 'undefined') {
89
- if (Array.isArray(props.children)) {
90
- this.children = props.children;
91
- }
92
- else {
93
- this.children = [props.children];
94
- }
95
- }
96
- return;
97
- }
98
- if (key === 'class') {
99
- this.classes = Props.classToString(props[key]);
100
- return;
101
- }
102
- if (key === 'style') {
103
- const style = props.style || '';
104
- if (typeof style === 'string') {
105
- style.split(';').map(s => s.split(':')).forEach(v => {
106
- if (!v[0] || !v[1]) {
107
- return;
108
- }
109
- this.styles.set(v[0].trim(), v[1].trim());
110
- });
111
- }
112
- else if (typeof style === 'object') {
113
- Object.keys(style).forEach(key => {
114
- this.styles.set(key, style[key]);
115
- });
116
- }
117
- return;
118
- }
119
- if (/^on[A-Z]/.test(key)) {
120
- const listener = props[key];
121
- if (typeof listener === 'function') {
122
- this.listeners[key.replace(/^on/, '').toLowerCase()] = listener;
123
- }
124
- else {
125
- this.attrs.set(key, listener);
126
- }
127
- return;
128
- }
129
- this.attrs.set(key, props[key]);
130
- });
131
- }
132
- static classToString(config) {
133
- if (!config) {
134
- return '';
135
- }
136
- if (typeof config === 'string') {
137
- return config;
138
- }
139
- else if (Array.isArray(config)) {
140
- return config.map(i => {
141
- return Props.classToString(i);
142
- }).join(' ');
143
- }
144
- else if (typeof config === 'object') {
145
- if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
146
- return config.toString();
147
- }
148
- const classes = [];
149
- for (const key in config) {
150
- if ({}.hasOwnProperty.call(config, key) && config[key]) {
151
- classes.push(key);
152
- }
153
- }
154
- return classes.join(' ');
155
- }
156
- }
157
- static classToArray(config) {
158
- const classes = [];
159
- if (!config) {
160
- return classes;
161
- }
162
- if (typeof config === 'string') {
163
- const items = config.match(/\S+/g);
164
- return items || classes;
165
- }
166
- else if (Array.isArray(config)) {
167
- for (const i of config) {
168
- classes.push(...Props.classToArray(i));
169
- }
170
- }
171
- else if (typeof config === 'object') {
172
- if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
173
- classes.push(config.toString());
174
- return classes;
175
- }
176
- for (const key in config) {
177
- if ({}.hasOwnProperty.call(config, key) && config[key]) {
178
- classes.push(key);
179
- }
180
- }
181
- }
182
- return classes;
183
- }
184
- }
185
- class JSXElement {
186
- constructor(name, config, key) {
187
- this.name = name;
188
- this.config = config;
189
- this.key = key;
190
- this.$$typeOf = this.name;
191
- this.props = new Props(config);
192
- }
193
- is(target) {
194
- return target.$$typeOf === this.$$typeOf;
195
- }
196
- }
197
-
198
47
  const componentSetupStack = [];
199
- const componentRendingStack = [];
200
- const derivedStack = [];
48
+ const signalDepsStack = [];
201
49
  const componentErrorFn = makeError('component');
202
50
  function getSetupContext(need = true) {
203
51
  const current = componentSetupStack[componentSetupStack.length - 1];
204
52
  if (!current && need) {
205
53
  // 防止因外部捕获异常引引起的缓存未清理的问题
206
- componentRendingStack.pop();
207
54
  throw componentErrorFn('cannot be called outside the component!');
208
55
  }
209
56
  return current;
210
57
  }
211
- function getRendingContext() {
212
- return componentRendingStack[componentRendingStack.length - 1];
213
- }
214
- function getDerivedContext() {
215
- return derivedStack[derivedStack.length - 1];
58
+ function getSignalDepsContext() {
59
+ return signalDepsStack[signalDepsStack.length - 1];
216
60
  }
217
61
  class JSXComponent {
218
62
  constructor(createInstance) {
@@ -229,12 +73,12 @@ class Component extends di.ReflectiveInjector {
229
73
  get changed() {
230
74
  return this._changed;
231
75
  }
232
- constructor(context, setup, config, key) {
76
+ constructor(context, type, props, key) {
233
77
  super(context, []);
234
- this.setup = setup;
235
- this.config = config;
78
+ this.type = type;
79
+ this.props = props;
236
80
  this.key = key;
237
- this.$$typeOf = this.setup;
81
+ this.$$typeOf = this.type;
238
82
  this.destroyCallbacks = [];
239
83
  this.mountCallbacks = [];
240
84
  this.propsChangedCallbacks = [];
@@ -244,7 +88,6 @@ class Component extends di.ReflectiveInjector {
244
88
  this.updatedDestroyCallbacks = [];
245
89
  this.propsChangedDestroyCallbacks = [];
246
90
  this.isFirstRending = true;
247
- this.props = new Props(config);
248
91
  this.parentComponent = this.parentInjector;
249
92
  }
250
93
  is(target) {
@@ -252,16 +95,14 @@ class Component extends di.ReflectiveInjector {
252
95
  }
253
96
  addProvide(providers) {
254
97
  providers = Array.isArray(providers) ? providers : [providers];
255
- providers.forEach(p => {
256
- this.normalizedProviders.push(di.normalizeProvider(p));
257
- });
98
+ this.normalizedProviders.unshift(...providers.map(i => di.normalizeProvider(i)));
258
99
  }
259
100
  init() {
260
101
  const self = this;
261
- const props = new Proxy(this.config || {}, {
102
+ const props = new Proxy(this.props, {
262
103
  get(_, key) {
263
- if (self.config) {
264
- return self.config[key];
104
+ if (self.props) {
105
+ return self.props[key];
265
106
  }
266
107
  },
267
108
  set() {
@@ -269,30 +110,30 @@ class Component extends di.ReflectiveInjector {
269
110
  if (isSetup) {
270
111
  componentSetupStack.pop();
271
112
  }
272
- if (isRending) {
273
- componentRendingStack.pop();
274
- }
275
113
  throw componentErrorFn('component props is readonly!');
276
114
  }
277
115
  });
278
116
  componentSetupStack.push(this);
279
117
  let isSetup = true;
280
- const render = this.setup(props);
118
+ const render = this.type(props);
281
119
  isSetup = false;
282
120
  componentSetupStack.pop();
283
- componentRendingStack.push(this);
284
- let isRending = true;
121
+ signalDepsStack.push([]);
285
122
  const template = render();
286
- isRending = false;
287
- componentRendingStack.pop();
123
+ const deps = signalDepsStack.pop();
124
+ this.unWatch = useEffect(deps, () => {
125
+ this.markAsDirtied();
126
+ });
288
127
  return {
289
128
  template,
290
129
  render: () => {
291
- componentRendingStack.push(this);
292
- isRending = true;
130
+ this.unWatch();
131
+ signalDepsStack.push([]);
293
132
  const template = render();
294
- isRending = false;
295
- componentRendingStack.pop();
133
+ const deps = signalDepsStack.pop();
134
+ this.unWatch = useEffect(deps, () => {
135
+ this.markAsDirtied();
136
+ });
296
137
  return template;
297
138
  }
298
139
  };
@@ -302,6 +143,9 @@ class Component extends di.ReflectiveInjector {
302
143
  this.markAsChanged();
303
144
  }
304
145
  markAsChanged() {
146
+ if (this._changed) {
147
+ return;
148
+ }
305
149
  this._changed = true;
306
150
  this.parentComponent.markAsChanged();
307
151
  }
@@ -318,8 +162,8 @@ class Component extends di.ReflectiveInjector {
318
162
  }
319
163
  }
320
164
  invokePropsChangedHooks(newProps) {
321
- const oldProps = this.config;
322
- this.config = newProps;
165
+ const oldProps = this.props;
166
+ this.props = newProps;
323
167
  this.propsChangedDestroyCallbacks.forEach(fn => {
324
168
  fn();
325
169
  });
@@ -332,6 +176,7 @@ class Component extends di.ReflectiveInjector {
332
176
  }
333
177
  }
334
178
  destroy() {
179
+ this.unWatch();
335
180
  this.updatedDestroyCallbacks.forEach(fn => {
336
181
  fn();
337
182
  });
@@ -380,7 +225,7 @@ class Component extends di.ReflectiveInjector {
380
225
  * }
381
226
  * ```
382
227
  */
383
- function onMount(callback) {
228
+ function onMounted(callback) {
384
229
  const component = getSetupContext();
385
230
  component.mountCallbacks.push(callback);
386
231
  }
@@ -523,18 +368,10 @@ const depsKey = Symbol('deps');
523
368
  * }
524
369
  */
525
370
  function useSignal(state) {
526
- const usedComponents = new Set();
527
371
  function signal() {
528
- const component = getRendingContext();
529
- const derivedContext = getDerivedContext();
530
- if (derivedContext) {
531
- derivedContext.push(signal);
532
- }
533
- if (component && !usedComponents.has(component)) {
534
- usedComponents.add(component);
535
- component.destroyCallbacks.push(() => {
536
- usedComponents.delete(component);
537
- });
372
+ const depsContext = getSignalDepsContext();
373
+ if (depsContext) {
374
+ depsContext.push(signal);
538
375
  }
539
376
  return state;
540
377
  }
@@ -543,9 +380,6 @@ function useSignal(state) {
543
380
  return;
544
381
  }
545
382
  state = newState;
546
- for (const component of usedComponents) {
547
- component.markAsDirtied();
548
- }
549
383
  for (const fn of signal[depsKey]) {
550
384
  fn();
551
385
  }
@@ -562,9 +396,9 @@ function useSignal(state) {
562
396
  */
563
397
  function useDerived(callback, isContinue) {
564
398
  const deps = [];
565
- derivedStack.push(deps);
399
+ signalDepsStack.push(deps);
566
400
  const data = callback();
567
- derivedStack.pop();
401
+ signalDepsStack.pop();
568
402
  const signal = useSignal(data);
569
403
  if (deps.length) {
570
404
  const unListen = useEffect(deps, () => {
@@ -635,12 +469,54 @@ function inject(token, notFoundValue, flags) {
635
469
  return component.parentInjector.get(token, notFoundValue, flags);
636
470
  }
637
471
 
472
+ const Fragment = function Fragment(props) {
473
+ return () => {
474
+ return props.children;
475
+ };
476
+ };
477
+ function jsx(setup, config, key) {
478
+ if (typeof setup === 'string') {
479
+ return new JSXElement(setup, config, key);
480
+ }
481
+ return new JSXComponent(function (context) {
482
+ return new Component(context, setup, config, key);
483
+ });
484
+ }
485
+ function jsxs(setup, config, key) {
486
+ if (typeof setup === 'string') {
487
+ return new JSXElement(setup, config, key);
488
+ }
489
+ return new JSXComponent(function (context) {
490
+ return new Component(context, setup, config, key);
491
+ });
492
+ }
493
+ class JSXText {
494
+ constructor(text) {
495
+ this.text = text;
496
+ this.$$typeOf = '#text';
497
+ }
498
+ is(target) {
499
+ return target.$$typeOf === this.$$typeOf;
500
+ }
501
+ }
502
+ class JSXElement {
503
+ constructor(type, props, key) {
504
+ this.type = type;
505
+ this.props = props;
506
+ this.key = key;
507
+ this.$$typeOf = this.type;
508
+ }
509
+ is(target) {
510
+ return target.$$typeOf === this.$$typeOf;
511
+ }
512
+ }
513
+
638
514
  /**
639
515
  * Viewfly 根组件,用于实现组件状态更新事件通知
640
516
  */
641
517
  class RootComponent extends Component {
642
518
  constructor(factory, parentInjector = new di.NullInjector()) {
643
- super(parentInjector, factory, null);
519
+ super(parentInjector, factory, {});
644
520
  this.changeEmitter = new stream.Subject();
645
521
  }
646
522
  markAsChanged() {
@@ -650,77 +526,67 @@ class RootComponent extends Component {
650
526
  }
651
527
 
652
528
  const refKey = 'ref';
653
- function getObjectChanges(target, source) {
529
+ function getObjectChanges(newProps, oldProps) {
654
530
  const changes = {
655
531
  remove: [],
656
- add: []
532
+ add: [],
533
+ replace: []
657
534
  };
658
- Object.keys(target).forEach(key => {
659
- const leftValue = target[key];
660
- if (!Reflect.has(source, key)) {
661
- changes.add.push([key, leftValue]);
662
- return;
663
- }
664
- const rightValue = source[key];
665
- if (leftValue === rightValue) {
535
+ Object.keys(newProps).forEach(key => {
536
+ const leftValue = newProps[key];
537
+ const rightValue = oldProps[key];
538
+ if (Reflect.has(oldProps, key)) {
539
+ if (leftValue !== rightValue) {
540
+ changes.replace.push([key, leftValue, rightValue]);
541
+ }
666
542
  return;
667
543
  }
668
544
  changes.add.push([key, leftValue]);
669
- changes.remove.push([key, rightValue]);
670
545
  });
671
- Object.keys(source).forEach(key => {
672
- if (!Reflect.has(target, key)) {
673
- changes.remove.push([key, source[key]]);
546
+ Object.keys(oldProps).forEach(key => {
547
+ if (!Reflect.has(newProps, key)) {
548
+ changes.remove.push([key, oldProps[key]]);
674
549
  }
675
550
  });
676
551
  return changes;
677
552
  }
678
- function getMapChanges(target, source) {
679
- const changes = {
680
- remove: [],
681
- set: []
682
- };
683
- target.forEach((value, key) => {
684
- const rightValue = source.get(key);
685
- if (value === rightValue) {
686
- return;
553
+ function classToString(config) {
554
+ if (!config) {
555
+ return '';
556
+ }
557
+ if (typeof config === 'string') {
558
+ return config;
559
+ }
560
+ else if (Array.isArray(config)) {
561
+ return config.map(i => {
562
+ return classToString(i);
563
+ }).join(' ');
564
+ }
565
+ else if (typeof config === 'object') {
566
+ if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
567
+ return config.toString();
687
568
  }
688
- changes.set.push([key, value]);
689
- });
690
- source.forEach((value, key) => {
691
- if (key === refKey && value instanceof Ref) {
692
- const newValue = target.get(key);
693
- if (value !== newValue) {
694
- changes.remove.push([key, value]);
569
+ const classes = [];
570
+ for (const key in config) {
571
+ if ({}.hasOwnProperty.call(config, key) && config[key]) {
572
+ classes.push(key);
695
573
  }
696
- return;
697
574
  }
698
- if (!target.has(key)) {
699
- changes.remove.push([key, value]);
575
+ return classes.join(' ');
576
+ }
577
+ }
578
+ function styleToObject(style) {
579
+ if (typeof style !== 'string') {
580
+ return style;
581
+ }
582
+ const obj = {};
583
+ style.split(';').map(s => s.split(':')).forEach(v => {
584
+ if (!v[0] || !v[1]) {
585
+ return;
700
586
  }
587
+ obj[v[0].trim()] = v[1].trim();
701
588
  });
702
- return changes;
703
- }
704
- const compareText = '0'.repeat(6);
705
- function getNodeChanges(newVNode, oldVNode) {
706
- const newProps = newVNode.props;
707
- const oldProps = oldVNode.props;
708
- const styleChanges = getMapChanges(newProps.styles, oldProps.styles);
709
- const attrChanges = getMapChanges(newProps.attrs, oldProps.attrs);
710
- const listenerChanges = getObjectChanges(newProps.listeners, oldProps.listeners);
711
- return {
712
- styleChanges,
713
- attrChanges,
714
- listenerChanges,
715
- isChanged: [
716
- attrChanges.set.length,
717
- attrChanges.remove.length,
718
- styleChanges.set.length,
719
- styleChanges.remove.length,
720
- listenerChanges.add.length,
721
- listenerChanges.remove.length
722
- ].join('') !== compareText
723
- };
589
+ return obj;
724
590
  }
725
591
 
726
592
  class RootComponentRef {
@@ -758,10 +624,12 @@ exports.Renderer = class Renderer {
758
624
  reconcile(component, context) {
759
625
  if (component.dirty) {
760
626
  this.applyChanges(component, context);
627
+ component.rendered();
761
628
  }
762
629
  else if (component.changed) {
763
630
  const atom = this.componentAtomCaches.get(component).atom.child;
764
631
  this.reconcileElement(atom, context);
632
+ component.rendered();
765
633
  }
766
634
  else {
767
635
  const prevSibling = this.getPrevSibling(component);
@@ -824,7 +692,6 @@ exports.Renderer = class Renderer {
824
692
  atom.child = null;
825
693
  }
826
694
  this.diff(atom.child, diffAtom, context, 0, 0);
827
- component.rendered();
828
695
  }
829
696
  diff(newAtom, oldAtom, context, expectIndex, index) {
830
697
  const oldChildren = [];
@@ -840,9 +707,9 @@ exports.Renderer = class Renderer {
840
707
  const changeCommits = {
841
708
  reuseComponent: (start, reusedAtom, expectIndex, diffIndex) => {
842
709
  commits.push(() => {
843
- const { isChanged } = getNodeChanges(start.jsxNode, reusedAtom.jsxNode);
844
- if (isChanged) {
845
- reusedAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
710
+ const { add, remove, replace } = getObjectChanges(start.jsxNode.props, reusedAtom.jsxNode.props);
711
+ if (add.length || remove.length || replace.length) {
712
+ reusedAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.props);
846
713
  }
847
714
  const newProps = start.jsxNode.props;
848
715
  start.jsxNode = reusedAtom.jsxNode;
@@ -917,7 +784,7 @@ exports.Renderer = class Renderer {
917
784
  });
918
785
  }
919
786
  };
920
- while (newAtom && !newAtom.nativeNode) {
787
+ while (newAtom) {
921
788
  this.createChanges(newAtom, expectIndex, oldChildren, changeCommits);
922
789
  newAtom = newAtom.sibling;
923
790
  expectIndex++;
@@ -975,7 +842,7 @@ exports.Renderer = class Renderer {
975
842
  isClean = true;
976
843
  }
977
844
  if (atom.jsxNode instanceof JSXElement) {
978
- const ref = atom.jsxNode.props.attrs.get(refKey);
845
+ const ref = atom.jsxNode.props[refKey];
979
846
  this.applyRefs(ref, atom.nativeNode, false);
980
847
  }
981
848
  }
@@ -1047,24 +914,23 @@ exports.Renderer = class Renderer {
1047
914
  }
1048
915
  createChainByComponentFactory(context, factory, parent) {
1049
916
  const component = factory.createInstance(context);
1050
- if (component.setup === Fragment) {
1051
- return this.createChainByChildren(component, component.props.children, parent);
1052
- }
917
+ // if (component.setup === Fragment) {
918
+ // const children = component.props.children
919
+ // return this.createChainByChildren(
920
+ // component,
921
+ // Array.isArray(children) ? children : [children],
922
+ // parent
923
+ // )
924
+ // }
1053
925
  return new Atom(component, parent);
1054
926
  }
1055
- createChainByTemplate(context, template, parent) {
1056
- if (template instanceof JSXElement) {
1057
- return this.createChainByJSXElement(context, template, parent);
1058
- }
1059
- if (template instanceof JSXComponent) {
1060
- return this.createChainByComponentFactory(context, template, parent);
1061
- }
1062
- return parent;
1063
- }
1064
927
  createChainByJSXElement(context, element, parent) {
1065
928
  const atom = new Atom(element, parent);
1066
- const children = this.createChainByChildren(context, element.props.children, atom);
1067
- this.link(atom, children);
929
+ if (Reflect.has(element.props, 'children')) {
930
+ const jsxChildren = element.props.children;
931
+ const children = this.createChainByChildren(context, Array.isArray(jsxChildren) ? jsxChildren : [jsxChildren], atom);
932
+ this.link(atom, children);
933
+ }
1068
934
  return atom;
1069
935
  }
1070
936
  createChainByJSXText(node, parent) {
@@ -1079,12 +945,7 @@ exports.Renderer = class Renderer {
1079
945
  }
1080
946
  if (item instanceof JSXComponent) {
1081
947
  const childAtom = this.createChainByComponentFactory(context, item, parent);
1082
- if (Array.isArray(childAtom)) {
1083
- atoms.push(...childAtom);
1084
- }
1085
- else {
1086
- atoms.push(childAtom);
1087
- }
948
+ atoms.push(childAtom);
1088
949
  continue;
1089
950
  }
1090
951
  if (typeof item === 'string' && item.length) {
@@ -1102,10 +963,8 @@ exports.Renderer = class Renderer {
1102
963
  return atoms;
1103
964
  }
1104
965
  linkTemplate(template, component, parent) {
1105
- if (template) {
1106
- const child = this.createChainByTemplate(component, template, parent);
1107
- this.link(parent, Array.isArray(child) ? child : [child]);
1108
- }
966
+ const children = Array.isArray(template) ? template : [template];
967
+ this.link(parent, this.createChainByChildren(component, children, parent));
1109
968
  }
1110
969
  link(parent, children) {
1111
970
  for (let i = 1; i < children.length; i++) {
@@ -1115,25 +974,38 @@ exports.Renderer = class Renderer {
1115
974
  parent.child = children[0] || null;
1116
975
  }
1117
976
  createElement(vNode) {
1118
- const nativeNode = this.nativeRenderer.createElement(vNode.name);
977
+ const nativeNode = this.nativeRenderer.createElement(vNode.type);
1119
978
  const props = vNode.props;
1120
979
  let bindingRefs;
1121
- props.attrs.forEach((value, key) => {
980
+ const keys = Object.keys(props);
981
+ for (const key of keys) {
982
+ if (key === 'children') {
983
+ continue;
984
+ }
985
+ if (key === 'class') {
986
+ this.nativeRenderer.setClass(nativeNode, classToString(props[key]));
987
+ continue;
988
+ }
989
+ if (key === 'style') {
990
+ const style = styleToObject(props.style);
991
+ Object.keys(style).forEach(key => {
992
+ this.nativeRenderer.setStyle(nativeNode, key, style[key]);
993
+ });
994
+ continue;
995
+ }
996
+ if (/^on[A-Z]/.test(key)) {
997
+ const listener = props[key];
998
+ if (typeof listener === 'function') {
999
+ this.nativeRenderer.listen(nativeNode, key.replace(/^on/, '').toLowerCase(), listener);
1000
+ }
1001
+ continue;
1002
+ }
1122
1003
  if (key === refKey) {
1123
- bindingRefs = value;
1124
- return;
1004
+ bindingRefs = props[key];
1005
+ continue;
1125
1006
  }
1126
- this.nativeRenderer.setProperty(nativeNode, key, value);
1127
- });
1128
- props.styles.forEach((value, key) => {
1129
- this.nativeRenderer.setStyle(nativeNode, key, value);
1130
- });
1131
- if (props.classes) {
1132
- this.nativeRenderer.setClass(nativeNode, props.classes);
1007
+ this.nativeRenderer.setProperty(nativeNode, key, props[key]);
1133
1008
  }
1134
- Object.keys(props.listeners).forEach(type => {
1135
- this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1136
- });
1137
1009
  return {
1138
1010
  nativeNode,
1139
1011
  applyRefs: () => {
@@ -1145,46 +1017,109 @@ exports.Renderer = class Renderer {
1145
1017
  return this.nativeRenderer.createTextNode(child.text);
1146
1018
  }
1147
1019
  updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
1148
- const newProps = newVNode.props;
1149
- const oldProps = oldVNode.props;
1150
- const styleChanges = getMapChanges(newProps.styles, oldProps.styles);
1151
- const attrChanges = getMapChanges(newProps.attrs, oldProps.attrs);
1152
- const listenerChanges = getObjectChanges(newProps.listeners, oldProps.listeners);
1153
- styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1154
- styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
1020
+ const changes = getObjectChanges(newVNode.props, oldVNode.props);
1155
1021
  let unBindRefs;
1156
- attrChanges.remove.forEach(([key, value]) => {
1022
+ let bindRefs;
1023
+ for (const [key, value] of changes.remove) {
1024
+ if (key === 'children') {
1025
+ continue;
1026
+ }
1027
+ if (key === 'class') {
1028
+ this.nativeRenderer.setClass(nativeNode, '');
1029
+ continue;
1030
+ }
1031
+ if (key === 'style') {
1032
+ Object.keys(styleToObject(value)).forEach(styleName => {
1033
+ this.nativeRenderer.removeStyle(nativeNode, styleName);
1034
+ });
1035
+ continue;
1036
+ }
1037
+ if (/^on[A-Z]/.test(key)) {
1038
+ if (typeof value === 'function') {
1039
+ this.nativeRenderer.unListen(nativeNode, key.replace(/^on/, '').toLowerCase(), value);
1040
+ }
1041
+ continue;
1042
+ }
1157
1043
  if (key === refKey) {
1158
1044
  unBindRefs = value;
1159
- return;
1045
+ continue;
1160
1046
  }
1161
1047
  this.nativeRenderer.removeProperty(nativeNode, key);
1162
- });
1163
- let bindRefs;
1164
- attrChanges.set.forEach(([key, value]) => {
1048
+ }
1049
+ for (const [key, newValue, oldValue] of changes.replace) {
1050
+ if (key === 'children') {
1051
+ continue;
1052
+ }
1053
+ if (key === 'class') {
1054
+ const oldClassName = classToString(oldValue);
1055
+ const newClassName = classToString(newValue);
1056
+ if (oldClassName !== newClassName) {
1057
+ this.nativeRenderer.setClass(nativeNode, newClassName);
1058
+ }
1059
+ continue;
1060
+ }
1061
+ if (key === 'style') {
1062
+ const styleChanges = getObjectChanges(styleToObject(newValue) || {}, styleToObject(oldValue) || {});
1063
+ for (const [styleName] of styleChanges.remove) {
1064
+ this.nativeRenderer.removeStyle(nativeNode, styleName);
1065
+ }
1066
+ for (const [styleName, styleValue] of [...styleChanges.add, ...styleChanges.replace]) {
1067
+ this.nativeRenderer.setStyle(nativeNode, styleName, styleValue);
1068
+ }
1069
+ continue;
1070
+ }
1071
+ if (/^on[A-Z]/.test(key)) {
1072
+ const listenType = key.replace(/^on/, '').toLowerCase();
1073
+ if (typeof oldValue === 'function') {
1074
+ this.nativeRenderer.unListen(nativeNode, listenType, oldValue);
1075
+ }
1076
+ if (typeof newValue === 'function') {
1077
+ this.nativeRenderer.listen(nativeNode, listenType, newValue);
1078
+ }
1079
+ continue;
1080
+ }
1081
+ if (key === refKey) {
1082
+ unBindRefs = oldValue;
1083
+ bindRefs = newValue;
1084
+ continue;
1085
+ }
1086
+ this.nativeRenderer.setProperty(nativeNode, key, newValue);
1087
+ }
1088
+ for (const [key, value] of changes.add) {
1089
+ if (key === 'children') {
1090
+ continue;
1091
+ }
1092
+ if (key === 'class') {
1093
+ this.nativeRenderer.setClass(nativeNode, classToString(value));
1094
+ continue;
1095
+ }
1096
+ if (key === 'style') {
1097
+ const styleObj = styleToObject(value);
1098
+ Object.keys(styleObj).forEach(styleName => {
1099
+ this.nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName]);
1100
+ });
1101
+ continue;
1102
+ }
1103
+ if (/^on[A-Z]/.test(key)) {
1104
+ if (typeof value === 'function') {
1105
+ this.nativeRenderer.listen(nativeNode, key.replace(/^on/, '').toLowerCase(), value);
1106
+ }
1107
+ continue;
1108
+ }
1165
1109
  if (key === refKey) {
1166
1110
  bindRefs = value;
1167
- return;
1111
+ continue;
1168
1112
  }
1169
1113
  this.nativeRenderer.setProperty(nativeNode, key, value);
1170
- });
1171
- if (newProps.classes !== oldProps.classes) {
1172
- this.nativeRenderer.setClass(nativeNode, newProps.classes);
1173
1114
  }
1174
- listenerChanges.remove.forEach(i => {
1175
- this.nativeRenderer.unListen(nativeNode, i[0], i[1]);
1176
- });
1177
- listenerChanges.add.forEach(i => {
1178
- this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1179
- });
1180
1115
  return () => {
1181
1116
  this.applyRefs(unBindRefs, nativeNode, false);
1182
1117
  this.applyRefs(bindRefs, nativeNode, true);
1183
1118
  };
1184
1119
  }
1185
1120
  applyRefs(refs, nativeNode, binding) {
1186
- refs = Array.isArray(refs) ? refs : [refs];
1187
- for (const item of refs) {
1121
+ const refList = Array.isArray(refs) ? refs : [refs];
1122
+ for (const item of refList) {
1188
1123
  if (item instanceof Ref) {
1189
1124
  binding ? item.bind(nativeNode) : item.unBind(nativeNode);
1190
1125
  }
@@ -1210,7 +1145,6 @@ class Viewfly extends di.ReflectiveInjector {
1210
1145
  provide: RootComponentRef,
1211
1146
  useFactory: () => {
1212
1147
  return {
1213
- host: config.host,
1214
1148
  component: this.rootComponent
1215
1149
  };
1216
1150
  }
@@ -1229,8 +1163,11 @@ class Viewfly extends di.ReflectiveInjector {
1229
1163
  }
1230
1164
  /**
1231
1165
  * 启动 Viewfly
1166
+ * @param host 应用根节点
1232
1167
  */
1233
- run() {
1168
+ mount(host) {
1169
+ const rootComponentRef = this.get(RootComponentRef);
1170
+ rootComponentRef.host = host;
1234
1171
  const renderer = this.get(exports.Renderer);
1235
1172
  renderer.render();
1236
1173
  if (this.config.autoUpdate === false) {
@@ -1265,7 +1202,6 @@ exports.JSXComponent = JSXComponent;
1265
1202
  exports.JSXElement = JSXElement;
1266
1203
  exports.JSXText = JSXText;
1267
1204
  exports.NativeRenderer = NativeRenderer;
1268
- exports.Props = Props;
1269
1205
  exports.Ref = Ref;
1270
1206
  exports.RootComponent = RootComponent;
1271
1207
  exports.RootComponentRef = RootComponentRef;
@@ -1275,7 +1211,7 @@ exports.jsx = jsx;
1275
1211
  exports.jsxs = jsxs;
1276
1212
  exports.makeError = makeError;
1277
1213
  exports.onDestroy = onDestroy;
1278
- exports.onMount = onMount;
1214
+ exports.onMounted = onMounted;
1279
1215
  exports.onPropsChanged = onPropsChanged;
1280
1216
  exports.onUpdated = onUpdated;
1281
1217
  exports.provide = provide;