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