@viewfly/core 0.0.1-alpha.6 → 0.0.1-alpha.8

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.
@@ -47,25 +47,29 @@ const jsxErrorFn = makeError('JSX');
47
47
  const Fragment = function Fragment() {
48
48
  throw jsxErrorFn('Fragment does not support calling.');
49
49
  };
50
- function jsx(setup, config) {
50
+ function jsx(setup, config, key) {
51
51
  if (typeof setup === 'string') {
52
- return new JSXElement(setup, config);
52
+ return new JSXElement(setup, config, key);
53
53
  }
54
54
  return new JSXComponent(function (context) {
55
- return new Component(context, setup, config);
55
+ return new Component(context, setup, config, key);
56
56
  });
57
57
  }
58
- function jsxs(setup, config) {
58
+ function jsxs(setup, config, key) {
59
59
  if (typeof setup === 'string') {
60
- return new JSXElement(setup, config);
60
+ return new JSXElement(setup, config, key);
61
61
  }
62
62
  return new JSXComponent(function (context) {
63
- return new Component(context, setup, config);
63
+ return new Component(context, setup, config, key);
64
64
  });
65
65
  }
66
66
  class JSXText {
67
67
  constructor(text) {
68
68
  this.text = text;
69
+ this.$$typeOf = '#text';
70
+ }
71
+ is(target) {
72
+ return target.$$typeOf === this.$$typeOf;
69
73
  }
70
74
  }
71
75
  function flatChildren(jsxNodes) {
@@ -90,7 +94,7 @@ class Props {
90
94
  constructor(props) {
91
95
  this.attrs = new Map();
92
96
  this.styles = new Map();
93
- this.classes = new Set();
97
+ this.classes = '';
94
98
  this.listeners = {};
95
99
  this.children = [];
96
100
  if (!props) {
@@ -109,7 +113,7 @@ class Props {
109
113
  return;
110
114
  }
111
115
  if (key === 'class') {
112
- this.classes = new Set(Props.classToArray(props[key]));
116
+ this.classes = Props.classToString(props[key]);
113
117
  return;
114
118
  }
115
119
  if (key === 'style') {
@@ -142,6 +146,31 @@ class Props {
142
146
  this.attrs.set(key, props[key]);
143
147
  });
144
148
  }
149
+ static classToString(config) {
150
+ if (!config) {
151
+ return '';
152
+ }
153
+ if (typeof config === 'string') {
154
+ return config;
155
+ }
156
+ else if (Array.isArray(config)) {
157
+ return config.map(i => {
158
+ return Props.classToString(i);
159
+ }).join(' ');
160
+ }
161
+ else if (typeof config === 'object') {
162
+ if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
163
+ return config.toString();
164
+ }
165
+ const classes = [];
166
+ for (const key in config) {
167
+ if ({}.hasOwnProperty.call(config, key) && config[key]) {
168
+ classes.push(key);
169
+ }
170
+ }
171
+ return classes.join(' ');
172
+ }
173
+ }
145
174
  static classToArray(config) {
146
175
  const classes = [];
147
176
  if (!config) {
@@ -171,11 +200,16 @@ class Props {
171
200
  }
172
201
  }
173
202
  class JSXElement {
174
- constructor(name, config) {
203
+ constructor(name, config, key) {
175
204
  this.name = name;
176
205
  this.config = config;
206
+ this.key = key;
207
+ this.$$typeOf = this.name;
177
208
  this.props = new Props(config);
178
209
  }
210
+ is(target) {
211
+ return target.$$typeOf === this.$$typeOf;
212
+ }
179
213
  }
180
214
 
181
215
  const componentSetupStack = [];
@@ -212,10 +246,12 @@ class Component extends ReflectiveInjector {
212
246
  get changed() {
213
247
  return this._changed;
214
248
  }
215
- constructor(context, setup, config) {
249
+ constructor(context, setup, config, key) {
216
250
  super(context, []);
217
251
  this.setup = setup;
218
252
  this.config = config;
253
+ this.key = key;
254
+ this.$$typeOf = this.setup;
219
255
  this.destroyCallbacks = [];
220
256
  this.mountCallbacks = [];
221
257
  this.propsChangedCallbacks = [];
@@ -228,6 +264,9 @@ class Component extends ReflectiveInjector {
228
264
  this.props = new Props(config);
229
265
  this.parentComponent = this.parentInjector;
230
266
  }
267
+ is(target) {
268
+ return target.$$typeOf === this.$$typeOf;
269
+ }
231
270
  addProvide(providers) {
232
271
  providers = Array.isArray(providers) ? providers : [providers];
233
272
  providers.forEach(p => {
@@ -633,21 +672,6 @@ function getObjectChanges(target, source) {
633
672
  remove: [],
634
673
  add: []
635
674
  };
636
- // if (!target) {
637
- // if (source) {
638
- // Object.keys(source).forEach(key => {
639
- // changes.remove.push([key, source[key]])
640
- // })
641
- // }
642
- // return changes
643
- // }
644
- //
645
- // if (!source) {
646
- // Object.keys(target).forEach(key => {
647
- // changes.add.push([key, target[key]])
648
- // })
649
- // return changes
650
- // }
651
675
  Object.keys(target).forEach(key => {
652
676
  const leftValue = target[key];
653
677
  if (!Reflect.has(source, key)) {
@@ -673,20 +697,6 @@ function getMapChanges(target, source) {
673
697
  remove: [],
674
698
  set: []
675
699
  };
676
- // if (!target) {
677
- // if (source) {
678
- // source.forEach((value, key) => {
679
- // changes.remove.push([key, value])
680
- // })
681
- // }
682
- // return changes
683
- // }
684
- // if (!source) {
685
- // target.forEach((value, key) => {
686
- // changes.set.push([key, value])
687
- // })
688
- // return changes
689
- // }
690
700
  target.forEach((value, key) => {
691
701
  const rightValue = source.get(key);
692
702
  if (value === rightValue) {
@@ -708,58 +718,22 @@ function getMapChanges(target, source) {
708
718
  });
709
719
  return changes;
710
720
  }
711
- function getSetChanges(target, source) {
712
- const changes = {
713
- add: [],
714
- remove: []
715
- };
716
- // if (!target) {
717
- // if (source) {
718
- // source.forEach(i => {
719
- // changes.remove.push(i)
720
- // })
721
- // }
722
- // return changes
723
- // }
724
- //
725
- // if (!source) {
726
- // target.forEach(i => {
727
- // changes.add.push(i)
728
- // })
729
- // return changes
730
- // }
731
- target.forEach(i => {
732
- if (!source.has(i)) {
733
- changes.add.push(i);
734
- }
735
- });
736
- source.forEach(i => {
737
- if (!target.has(i)) {
738
- changes.remove.push(i);
739
- }
740
- });
741
- return changes;
742
- }
743
- const compareText = '0'.repeat(8);
721
+ const compareText = '0'.repeat(6);
744
722
  function getNodeChanges(newVNode, oldVNode) {
745
723
  const newProps = newVNode.props;
746
724
  const oldProps = oldVNode.props;
747
725
  const styleChanges = getMapChanges(newProps.styles, oldProps.styles);
748
726
  const attrChanges = getMapChanges(newProps.attrs, oldProps.attrs);
749
- const classesChanges = getSetChanges(newProps.classes, oldProps.classes);
750
727
  const listenerChanges = getObjectChanges(newProps.listeners, oldProps.listeners);
751
728
  return {
752
729
  styleChanges,
753
730
  attrChanges,
754
- classesChanges,
755
731
  listenerChanges,
756
732
  isChanged: [
757
733
  attrChanges.set.length,
758
734
  attrChanges.remove.length,
759
735
  styleChanges.set.length,
760
736
  styleChanges.remove.length,
761
- classesChanges.add.length,
762
- classesChanges.remove.length,
763
737
  listenerChanges.add.length,
764
738
  listenerChanges.remove.length
765
739
  ].join('') !== compareText
@@ -785,10 +759,10 @@ let Renderer = class Renderer {
785
759
  }
786
760
  render() {
787
761
  const { component, host } = this.rootComponentRef;
788
- const chain = new Atom(component, null);
789
- const children = this.buildView(chain);
790
- children.forEach(child => {
791
- this.nativeRenderer.appendChild(host, child);
762
+ const atom = new Atom(component, null);
763
+ this.buildView(atom, {
764
+ isParent: true,
765
+ host
792
766
  });
793
767
  }
794
768
  refresh() {
@@ -866,81 +840,149 @@ let Renderer = class Renderer {
866
840
  else {
867
841
  atom.child = null;
868
842
  }
869
- this.diff(atom.child, diffAtom, context);
843
+ this.diff(atom.child, diffAtom, context, 0, 0);
870
844
  component.rendered();
871
845
  }
872
- diff(start, diffAtom, context) {
846
+ diff(newAtom, oldAtom, context, expectIndex, index) {
873
847
  const oldChildren = [];
874
- while (diffAtom) {
875
- oldChildren.push(diffAtom);
876
- diffAtom = diffAtom.sibling;
848
+ while (oldAtom) {
849
+ oldChildren.push({
850
+ index,
851
+ atom: oldAtom
852
+ });
853
+ oldAtom = oldAtom.sibling;
854
+ index++;
877
855
  }
878
856
  const commits = [];
879
- const addReuseCommit = (start, reusedAtom) => {
880
- commits.push(() => {
881
- const isComponent = start.jsxNode instanceof Component;
882
- if (!isComponent) {
883
- const host = context.host;
884
- if (context.isParent) {
885
- this.nativeRenderer.prependChild(host, start.nativeNode);
857
+ const changeCommits = {
858
+ reuseComponent: (start, reusedAtom, expectIndex, diffIndex) => {
859
+ commits.push(() => {
860
+ const { isChanged } = getNodeChanges(start.jsxNode, reusedAtom.jsxNode);
861
+ if (isChanged) {
862
+ reusedAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
886
863
  }
887
- else {
888
- this.nativeRenderer.insertAfter(start.nativeNode, host);
864
+ const newProps = start.jsxNode.props;
865
+ start.jsxNode = reusedAtom.jsxNode;
866
+ start.jsxNode.props = newProps;
867
+ const { render } = this.componentAtomCaches.get(start.jsxNode);
868
+ const template = render();
869
+ if (template) {
870
+ this.linkTemplate(template, start.jsxNode, start);
889
871
  }
890
- context.host = start.nativeNode;
891
- context.isParent = false;
892
- }
893
- if (start.child) {
894
- const childContext = start.jsxNode instanceof JSXElement ? {
895
- host: start.nativeNode,
896
- isParent: true
897
- } : context;
898
- this.diff(start.child, reusedAtom.child, childContext);
899
- }
900
- else if (reusedAtom.child) {
901
- let atom = reusedAtom.child;
902
- while (atom) {
903
- this.cleanView(atom, false);
904
- atom = atom.sibling;
872
+ this.componentAtomCaches.set(start.jsxNode, {
873
+ render,
874
+ atom: start
875
+ });
876
+ if (start.child) {
877
+ this.diff(start.child, reusedAtom.child, context, expectIndex, diffIndex);
878
+ }
879
+ else if (reusedAtom.child) {
880
+ let atom = reusedAtom.child;
881
+ while (atom) {
882
+ this.cleanView(atom, false);
883
+ atom = atom.sibling;
884
+ }
905
885
  }
906
- }
907
- if (isComponent) {
908
886
  start.jsxNode.rendered();
909
- }
910
- });
911
- };
912
- const addCreateCommit = (start) => {
913
- commits.push(() => {
914
- const children = this.createViewByAtom(start);
915
- children.forEach(child => {
916
- if (context.isParent) {
917
- this.nativeRenderer.prependChild(context.host, child);
887
+ });
888
+ },
889
+ reuseElement: (newAtom, oldAtom, expectIndex, oldIndex) => {
890
+ commits.push(() => {
891
+ newAtom.nativeNode = oldAtom.nativeNode;
892
+ const host = context.host;
893
+ if (expectIndex !== oldIndex) {
894
+ if (context.isParent) {
895
+ this.nativeRenderer.prependChild(host, newAtom.nativeNode);
896
+ }
897
+ else {
898
+ this.nativeRenderer.insertAfter(newAtom.nativeNode, host);
899
+ }
918
900
  }
919
- else {
920
- this.nativeRenderer.insertAfter(child, context.host);
901
+ context.host = newAtom.nativeNode;
902
+ context.isParent = false;
903
+ const applyRefs = this.updateNativeNodeProperties(newAtom.jsxNode, oldAtom.jsxNode, newAtom.nativeNode);
904
+ if (newAtom.child) {
905
+ this.diff(newAtom.child, oldAtom.child, {
906
+ host: newAtom.nativeNode,
907
+ isParent: true
908
+ }, 0, 0);
921
909
  }
922
- context.host = child;
910
+ else if (oldAtom.child) {
911
+ let atom = oldAtom.child;
912
+ while (atom) {
913
+ this.cleanView(atom, false);
914
+ atom = atom.sibling;
915
+ }
916
+ }
917
+ if (applyRefs) {
918
+ applyRefs();
919
+ }
920
+ });
921
+ },
922
+ reuseText: (newAtom, oldAtom) => {
923
+ commits.push(() => {
924
+ const nativeNode = oldAtom.nativeNode;
925
+ if (newAtom.jsxNode.text !== oldAtom.jsxNode.text) {
926
+ this.nativeRenderer.syncTextContent(nativeNode, newAtom.jsxNode.text);
927
+ }
928
+ newAtom.nativeNode = nativeNode;
929
+ context.host = nativeNode;
923
930
  context.isParent = false;
924
931
  });
925
- });
926
- };
927
- while (start && !start.nativeNode) {
928
- const reusedAtom = this.reuseAndUpdate(start, oldChildren);
929
- if (reusedAtom) {
930
- addReuseCommit(start, reusedAtom);
931
- }
932
- else {
933
- addCreateCommit(start);
932
+ },
933
+ create: (start) => {
934
+ commits.push(() => {
935
+ this.buildView(start, context);
936
+ });
934
937
  }
935
- start = start.sibling;
938
+ };
939
+ while (newAtom && !newAtom.nativeNode) {
940
+ this.createChanges(newAtom, expectIndex, oldChildren, changeCommits);
941
+ newAtom = newAtom.sibling;
942
+ expectIndex++;
936
943
  }
937
- for (const atom of oldChildren) {
938
- this.cleanView(atom, false);
944
+ for (const item of oldChildren) {
945
+ this.cleanView(item.atom, false);
939
946
  }
940
- for (const commit of commits) {
947
+ for (let i = 0; i < commits.length; i++) {
948
+ const commit = commits[i];
941
949
  commit();
942
950
  }
943
951
  }
952
+ createChanges(newAtom, lastIndex, oldChildren, changeCommits) {
953
+ let isReuse = false;
954
+ for (let i = 0; i < oldChildren.length; i++) {
955
+ const { atom: diffAtom, index: diffIndex } = oldChildren[i];
956
+ const key = newAtom.jsxNode.key;
957
+ const diffKey = diffAtom.jsxNode.key;
958
+ if (key !== undefined && diffKey !== undefined) {
959
+ if (diffKey !== key) {
960
+ continue;
961
+ }
962
+ isReuse = lastIndex > diffIndex;
963
+ }
964
+ if (newAtom.jsxNode.is(diffAtom.jsxNode)) {
965
+ if (newAtom.jsxNode instanceof JSXElement) {
966
+ if (isReuse) {
967
+ this.nativeRenderer.remove(diffAtom.nativeNode);
968
+ }
969
+ changeCommits.reuseElement(newAtom, diffAtom, lastIndex, diffIndex);
970
+ }
971
+ else if (newAtom.jsxNode instanceof JSXText) {
972
+ changeCommits.reuseText(newAtom, diffAtom);
973
+ }
974
+ else {
975
+ if (isReuse) {
976
+ this.temporarilyRemove(diffAtom);
977
+ }
978
+ changeCommits.reuseComponent(newAtom, diffAtom, lastIndex, diffIndex);
979
+ }
980
+ oldChildren.splice(i, 1);
981
+ return;
982
+ }
983
+ }
984
+ changeCommits.create(newAtom);
985
+ }
944
986
  cleanView(atom, isClean) {
945
987
  if (atom.nativeNode) {
946
988
  if (!isClean) {
@@ -961,148 +1003,74 @@ let Renderer = class Renderer {
961
1003
  atom.jsxNode.destroy();
962
1004
  }
963
1005
  }
964
- reuseAndUpdate(start, oldChildren) {
965
- for (let i = 0; i < oldChildren.length; i++) {
966
- const diffAtom = oldChildren[i];
967
- if (start.jsxNode instanceof JSXElement) {
968
- if (diffAtom.jsxNode instanceof JSXElement && start.jsxNode.name === diffAtom.jsxNode.name) {
969
- const nativeNode = diffAtom.nativeNode;
970
- start.nativeNode = nativeNode;
971
- this.updateNativeNodeProperties(start.jsxNode, diffAtom.jsxNode, nativeNode);
972
- oldChildren.splice(i, 1);
973
- return diffAtom;
974
- }
1006
+ temporarilyRemove(atom) {
1007
+ let next = atom.child;
1008
+ while (next) {
1009
+ if (next.jsxNode instanceof Component) {
1010
+ this.temporarilyRemove(next);
975
1011
  }
976
- else if (start.jsxNode instanceof JSXText) {
977
- if (diffAtom.jsxNode instanceof JSXText) {
978
- const nativeNode = diffAtom.nativeNode;
979
- if (start.jsxNode.text !== diffAtom.jsxNode.text) {
980
- this.nativeRenderer.syncTextContent(nativeNode, start.jsxNode.text);
981
- }
982
- start.nativeNode = nativeNode;
983
- oldChildren.splice(i, 1);
984
- return diffAtom;
985
- }
986
- }
987
- else if (diffAtom.jsxNode instanceof Component) {
988
- if (start.jsxNode.setup === diffAtom.jsxNode.setup) {
989
- const { isChanged } = getNodeChanges(start.jsxNode, diffAtom.jsxNode);
990
- if (isChanged) {
991
- diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
992
- }
993
- const newProps = start.jsxNode.props;
994
- start.jsxNode = diffAtom.jsxNode;
995
- start.jsxNode.props = newProps;
996
- const { render } = this.componentAtomCaches.get(start.jsxNode);
997
- const template = render();
998
- if (template) {
999
- this.linkTemplate(template, start.jsxNode, start);
1000
- }
1001
- this.componentAtomCaches.set(start.jsxNode, {
1002
- render,
1003
- atom: start
1004
- });
1005
- oldChildren.splice(i, 1);
1006
- return diffAtom;
1007
- }
1012
+ else {
1013
+ this.nativeRenderer.remove(next.nativeNode);
1008
1014
  }
1015
+ next = next.sibling;
1009
1016
  }
1010
- return null;
1011
1017
  }
1012
- createViewByAtom(atom) {
1013
- if (atom.jsxNode instanceof JSXElement) {
1014
- const nativeNode = this.createElement(atom.jsxNode);
1015
- atom.nativeNode = nativeNode;
1016
- if (atom.child) {
1017
- const children = this.buildView(atom.child);
1018
- for (const child of children) {
1019
- this.nativeRenderer.appendChild(nativeNode, child);
1020
- }
1018
+ buildView(atom, context) {
1019
+ if (atom.jsxNode instanceof Component) {
1020
+ this.componentRender(atom.jsxNode, atom);
1021
+ let child = atom.child;
1022
+ while (child) {
1023
+ this.buildView(child, context);
1024
+ child = child.sibling;
1021
1025
  }
1022
- return [nativeNode];
1026
+ atom.jsxNode.rendered();
1023
1027
  }
1024
- else if (atom.jsxNode instanceof JSXText) {
1025
- const nativeNode = this.createTextNode(atom.jsxNode);
1028
+ else {
1029
+ let nativeNode;
1030
+ let applyRefs = null;
1031
+ if (atom.jsxNode instanceof JSXElement) {
1032
+ const { nativeNode: n, applyRefs: a } = this.createElement(atom.jsxNode);
1033
+ nativeNode = n;
1034
+ applyRefs = a;
1035
+ }
1036
+ else {
1037
+ nativeNode = this.createTextNode(atom.jsxNode);
1038
+ }
1026
1039
  atom.nativeNode = nativeNode;
1027
- return [nativeNode];
1028
- }
1029
- const { template, render } = atom.jsxNode.init();
1030
- this.componentAtomCaches.set(atom.jsxNode, {
1031
- atom,
1032
- render
1033
- });
1034
- if (template) {
1035
- this.linkTemplate(template, atom.jsxNode, atom);
1036
- }
1037
- if (atom.child) {
1038
- return this.buildView(atom.child);
1039
- }
1040
- return [];
1041
- }
1042
- buildView(chain) {
1043
- const context = [];
1044
- const children = [];
1045
- function getContext() {
1046
- return context[context.length - 1];
1047
- }
1048
- let atom = chain;
1049
- const stopAtom = chain.parent;
1050
- wrap: while (atom) {
1051
- if (atom.jsxNode instanceof Component) {
1052
- this.componentRender(atom.jsxNode, atom);
1053
- if (atom.child) {
1054
- atom = atom.child;
1055
- continue;
1056
- }
1057
- atom.jsxNode.rendered();
1040
+ if (context.isParent) {
1041
+ this.nativeRenderer.prependChild(context.host, nativeNode);
1058
1042
  }
1059
1043
  else {
1060
- const host = getContext();
1061
- const nativeNode = atom.jsxNode instanceof JSXElement ? this.createElement(atom.jsxNode) : this.createTextNode(atom.jsxNode);
1062
- atom.nativeNode = nativeNode;
1063
- if (host) {
1064
- this.nativeRenderer.appendChild(host, nativeNode);
1065
- }
1066
- else {
1067
- children.push(nativeNode);
1068
- }
1069
- if (atom.child) {
1070
- context.push(nativeNode);
1071
- atom = atom.child;
1072
- continue;
1073
- }
1044
+ this.nativeRenderer.insertAfter(nativeNode, context.host);
1074
1045
  }
1075
- while (atom) {
1076
- if (atom.sibling) {
1077
- atom = atom.sibling;
1078
- break;
1079
- }
1080
- atom = atom.parent;
1081
- const isComponent = (atom === null || atom === void 0 ? void 0 : atom.jsxNode) instanceof Component;
1082
- if (isComponent) {
1083
- atom.jsxNode.rendered();
1084
- }
1085
- if (atom === stopAtom) {
1086
- break wrap;
1087
- }
1088
- if (isComponent) {
1089
- continue;
1046
+ if (atom.jsxNode instanceof JSXElement) {
1047
+ const childContext = {
1048
+ isParent: true,
1049
+ host: nativeNode
1050
+ };
1051
+ let child = atom.child;
1052
+ while (child) {
1053
+ this.buildView(child, childContext);
1054
+ child = child.sibling;
1090
1055
  }
1091
- context.pop();
1056
+ }
1057
+ context.host = nativeNode;
1058
+ context.isParent = false;
1059
+ if (applyRefs) {
1060
+ applyRefs();
1092
1061
  }
1093
1062
  }
1094
- return children;
1095
1063
  }
1096
- componentRender(component, parent) {
1064
+ componentRender(component, from) {
1097
1065
  const { template, render } = component.init();
1098
1066
  if (template) {
1099
- this.linkTemplate(template, component, parent);
1067
+ this.linkTemplate(template, component, from);
1100
1068
  }
1101
1069
  this.componentAtomCaches.set(component, {
1102
1070
  render,
1103
- atom: parent
1071
+ atom: from
1104
1072
  });
1105
- return parent;
1073
+ return from;
1106
1074
  }
1107
1075
  createChainByComponentFactory(context, factory, parent) {
1108
1076
  const component = factory.createInstance(context);
@@ -1158,34 +1126,39 @@ let Renderer = class Renderer {
1158
1126
  createElement(vNode) {
1159
1127
  const nativeNode = this.nativeRenderer.createElement(vNode.name);
1160
1128
  const props = vNode.props;
1161
- if (props) {
1162
- let bindingRefs;
1163
- props.attrs.forEach((value, key) => {
1164
- if (key === refKey) {
1165
- bindingRefs = value;
1166
- return;
1167
- }
1168
- this.nativeRenderer.setProperty(nativeNode, key, value);
1169
- });
1170
- props.styles.forEach((value, key) => {
1171
- this.nativeRenderer.setStyle(nativeNode, key, value);
1172
- });
1173
- props.classes.forEach(k => this.nativeRenderer.addClass(nativeNode, k));
1174
- Object.keys(props.listeners).forEach(type => {
1175
- this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1176
- });
1177
- this.applyRefs(bindingRefs, nativeNode, true);
1129
+ let bindingRefs;
1130
+ props.attrs.forEach((value, key) => {
1131
+ if (key === refKey) {
1132
+ bindingRefs = value;
1133
+ return;
1134
+ }
1135
+ this.nativeRenderer.setProperty(nativeNode, key, value);
1136
+ });
1137
+ props.styles.forEach((value, key) => {
1138
+ this.nativeRenderer.setStyle(nativeNode, key, value);
1139
+ });
1140
+ if (props.classes) {
1141
+ this.nativeRenderer.setClass(nativeNode, props.classes);
1178
1142
  }
1179
- return nativeNode;
1143
+ Object.keys(props.listeners).forEach(type => {
1144
+ this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1145
+ });
1146
+ return {
1147
+ nativeNode,
1148
+ applyRefs: () => {
1149
+ this.applyRefs(bindingRefs, nativeNode, true);
1150
+ }
1151
+ };
1180
1152
  }
1181
1153
  createTextNode(child) {
1182
1154
  return this.nativeRenderer.createTextNode(child.text);
1183
1155
  }
1184
1156
  updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
1185
- const { styleChanges, attrChanges, classesChanges, listenerChanges, isChanged } = getNodeChanges(newVNode, oldVNode);
1186
- if (!isChanged) {
1187
- return;
1188
- }
1157
+ const newProps = newVNode.props;
1158
+ const oldProps = oldVNode.props;
1159
+ const styleChanges = getMapChanges(newProps.styles, oldProps.styles);
1160
+ const attrChanges = getMapChanges(newProps.attrs, oldProps.attrs);
1161
+ const listenerChanges = getObjectChanges(newProps.listeners, oldProps.listeners);
1189
1162
  styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1190
1163
  styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
1191
1164
  let unBindRefs;
@@ -1204,16 +1177,19 @@ let Renderer = class Renderer {
1204
1177
  }
1205
1178
  this.nativeRenderer.setProperty(nativeNode, key, value);
1206
1179
  });
1207
- classesChanges.remove.forEach(i => this.nativeRenderer.removeClass(nativeNode, i));
1208
- classesChanges.add.forEach(i => this.nativeRenderer.addClass(nativeNode, i));
1180
+ if (newProps.classes !== oldProps.classes) {
1181
+ this.nativeRenderer.setClass(nativeNode, newProps.classes);
1182
+ }
1209
1183
  listenerChanges.remove.forEach(i => {
1210
1184
  this.nativeRenderer.unListen(nativeNode, i[0], i[1]);
1211
1185
  });
1212
1186
  listenerChanges.add.forEach(i => {
1213
1187
  this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1214
1188
  });
1215
- this.applyRefs(unBindRefs, nativeNode, false);
1216
- this.applyRefs(bindRefs, nativeNode, true);
1189
+ return () => {
1190
+ this.applyRefs(unBindRefs, nativeNode, false);
1191
+ this.applyRefs(bindRefs, nativeNode, true);
1192
+ };
1217
1193
  }
1218
1194
  applyRefs(refs, nativeNode, binding) {
1219
1195
  refs = Array.isArray(refs) ? refs : [refs];