@viewfly/core 0.0.1-alpha.5 → 0.0.1-alpha.7

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.
@@ -18,7 +18,7 @@ export declare class Renderer {
18
18
  private diff;
19
19
  private cleanView;
20
20
  private reuseAndUpdate;
21
- private createViewByAtom;
21
+ private temporarilyRemove;
22
22
  private buildView;
23
23
  private componentRender;
24
24
  private createChainByComponentFactory;
@@ -47,20 +47,20 @@ 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 {
@@ -171,9 +171,10 @@ class Props {
171
171
  }
172
172
  }
173
173
  class JSXElement {
174
- constructor(name, config) {
174
+ constructor(name, config, key) {
175
175
  this.name = name;
176
176
  this.config = config;
177
+ this.key = key;
177
178
  this.props = new Props(config);
178
179
  }
179
180
  }
@@ -212,10 +213,11 @@ class Component extends ReflectiveInjector {
212
213
  get changed() {
213
214
  return this._changed;
214
215
  }
215
- constructor(context, setup, config) {
216
+ constructor(context, setup, config, key) {
216
217
  super(context, []);
217
218
  this.setup = setup;
218
219
  this.config = config;
220
+ this.key = key;
219
221
  this.destroyCallbacks = [];
220
222
  this.mountCallbacks = [];
221
223
  this.propsChangedCallbacks = [];
@@ -785,10 +787,10 @@ let Renderer = class Renderer {
785
787
  }
786
788
  render() {
787
789
  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);
790
+ const atom = new Atom(component, null);
791
+ this.buildView(atom, {
792
+ isParent: true,
793
+ host
792
794
  });
793
795
  }
794
796
  refresh() {
@@ -871,12 +873,17 @@ let Renderer = class Renderer {
871
873
  }
872
874
  diff(start, diffAtom, context) {
873
875
  const oldChildren = [];
876
+ let index = 0;
874
877
  while (diffAtom) {
875
- oldChildren.push(diffAtom);
878
+ oldChildren.push({
879
+ index,
880
+ atom: diffAtom
881
+ });
876
882
  diffAtom = diffAtom.sibling;
883
+ index++;
877
884
  }
878
885
  const commits = [];
879
- const addReuseCommit = (start, reusedAtom) => {
886
+ const addUpdateCommit = (start, reusedAtom) => {
880
887
  commits.push(() => {
881
888
  const isComponent = start.jsxNode instanceof Component;
882
889
  if (!isComponent) {
@@ -890,6 +897,10 @@ let Renderer = class Renderer {
890
897
  context.host = start.nativeNode;
891
898
  context.isParent = false;
892
899
  }
900
+ let applyRefs = null;
901
+ if (start.jsxNode instanceof JSXElement) {
902
+ applyRefs = this.updateNativeNodeProperties(start.jsxNode, reusedAtom.jsxNode, start.nativeNode);
903
+ }
893
904
  if (start.child) {
894
905
  const childContext = start.jsxNode instanceof JSXElement ? {
895
906
  host: start.nativeNode,
@@ -898,7 +909,14 @@ let Renderer = class Renderer {
898
909
  this.diff(start.child, reusedAtom.child, childContext);
899
910
  }
900
911
  else if (reusedAtom.child) {
901
- this.cleanView(reusedAtom.child, false);
912
+ let atom = reusedAtom.child;
913
+ while (atom) {
914
+ this.cleanView(atom, false);
915
+ atom = atom.sibling;
916
+ }
917
+ }
918
+ if (applyRefs) {
919
+ applyRefs();
902
920
  }
903
921
  if (isComponent) {
904
922
  start.jsxNode.rendered();
@@ -907,31 +925,23 @@ let Renderer = class Renderer {
907
925
  };
908
926
  const addCreateCommit = (start) => {
909
927
  commits.push(() => {
910
- const children = this.createViewByAtom(start);
911
- children.forEach(child => {
912
- if (context.isParent) {
913
- this.nativeRenderer.prependChild(context.host, child);
914
- }
915
- else {
916
- this.nativeRenderer.insertAfter(child, context.host);
917
- }
918
- context.host = child;
919
- context.isParent = false;
920
- });
928
+ this.buildView(start, context);
921
929
  });
922
930
  };
931
+ let i = 0;
923
932
  while (start && !start.nativeNode) {
924
- const reusedAtom = this.reuseAndUpdate(start, oldChildren);
933
+ const reusedAtom = this.reuseAndUpdate(start, i, oldChildren);
925
934
  if (reusedAtom) {
926
- addReuseCommit(start, reusedAtom);
935
+ addUpdateCommit(start, reusedAtom);
927
936
  }
928
937
  else {
929
938
  addCreateCommit(start);
930
939
  }
940
+ i++;
931
941
  start = start.sibling;
932
942
  }
933
- for (const atom of oldChildren) {
934
- this.cleanView(atom, false);
943
+ for (const item of oldChildren) {
944
+ this.cleanView(item.atom, false);
935
945
  }
936
946
  for (const commit of commits) {
937
947
  commit();
@@ -957,14 +967,25 @@ let Renderer = class Renderer {
957
967
  atom.jsxNode.destroy();
958
968
  }
959
969
  }
960
- reuseAndUpdate(start, oldChildren) {
970
+ reuseAndUpdate(start, lastIndex, oldChildren) {
971
+ let isReuse = false;
961
972
  for (let i = 0; i < oldChildren.length; i++) {
962
- const diffAtom = oldChildren[i];
973
+ const { atom: diffAtom, index: diffIndex } = oldChildren[i];
974
+ const key = start.jsxNode.key;
975
+ const diffKey = diffAtom.jsxNode.key;
976
+ if (key !== undefined && diffKey !== undefined) {
977
+ if (diffKey !== key) {
978
+ continue;
979
+ }
980
+ isReuse = lastIndex > diffIndex;
981
+ }
963
982
  if (start.jsxNode instanceof JSXElement) {
964
983
  if (diffAtom.jsxNode instanceof JSXElement && start.jsxNode.name === diffAtom.jsxNode.name) {
965
984
  const nativeNode = diffAtom.nativeNode;
985
+ if (isReuse) {
986
+ this.nativeRenderer.remove(nativeNode);
987
+ }
966
988
  start.nativeNode = nativeNode;
967
- this.updateNativeNodeProperties(start.jsxNode, diffAtom.jsxNode, nativeNode);
968
989
  oldChildren.splice(i, 1);
969
990
  return diffAtom;
970
991
  }
@@ -982,6 +1003,9 @@ let Renderer = class Renderer {
982
1003
  }
983
1004
  else if (diffAtom.jsxNode instanceof Component) {
984
1005
  if (start.jsxNode.setup === diffAtom.jsxNode.setup) {
1006
+ if (isReuse) {
1007
+ this.temporarilyRemove(diffAtom);
1008
+ }
985
1009
  const { isChanged } = getNodeChanges(start.jsxNode, diffAtom.jsxNode);
986
1010
  if (isChanged) {
987
1011
  diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
@@ -1005,100 +1029,74 @@ let Renderer = class Renderer {
1005
1029
  }
1006
1030
  return null;
1007
1031
  }
1008
- createViewByAtom(atom) {
1009
- if (atom.jsxNode instanceof JSXElement) {
1010
- const nativeNode = this.createElement(atom.jsxNode);
1011
- atom.nativeNode = nativeNode;
1012
- if (atom.child) {
1013
- const children = this.buildView(atom.child);
1014
- for (const child of children) {
1015
- this.nativeRenderer.appendChild(nativeNode, child);
1016
- }
1032
+ temporarilyRemove(atom) {
1033
+ let next = atom.child;
1034
+ while (next) {
1035
+ if (next.jsxNode instanceof Component) {
1036
+ this.temporarilyRemove(next);
1017
1037
  }
1018
- return [nativeNode];
1019
- }
1020
- else if (atom.jsxNode instanceof JSXText) {
1021
- const nativeNode = this.createTextNode(atom.jsxNode);
1022
- atom.nativeNode = nativeNode;
1023
- return [nativeNode];
1024
- }
1025
- const { template, render } = atom.jsxNode.init();
1026
- this.componentAtomCaches.set(atom.jsxNode, {
1027
- atom,
1028
- render
1029
- });
1030
- if (template) {
1031
- this.linkTemplate(template, atom.jsxNode, atom);
1032
- }
1033
- if (atom.child) {
1034
- return this.buildView(atom.child);
1038
+ else {
1039
+ this.nativeRenderer.remove(next.nativeNode);
1040
+ }
1041
+ next = next.sibling;
1035
1042
  }
1036
- return [];
1037
1043
  }
1038
- buildView(chain) {
1039
- const context = [];
1040
- const children = [];
1041
- function getContext() {
1042
- return context[context.length - 1];
1043
- }
1044
- let atom = chain;
1045
- const stopAtom = chain.parent;
1046
- wrap: while (atom) {
1047
- if (atom.jsxNode instanceof Component) {
1048
- this.componentRender(atom.jsxNode, atom);
1049
- if (atom.child) {
1050
- atom = atom.child;
1051
- continue;
1052
- }
1053
- atom.jsxNode.rendered();
1044
+ buildView(atom, context) {
1045
+ if (atom.jsxNode instanceof Component) {
1046
+ this.componentRender(atom.jsxNode, atom);
1047
+ let child = atom.child;
1048
+ while (child) {
1049
+ this.buildView(child, context);
1050
+ child = child.sibling;
1051
+ }
1052
+ atom.jsxNode.rendered();
1053
+ }
1054
+ else {
1055
+ let nativeNode;
1056
+ let applyRefs = null;
1057
+ if (atom.jsxNode instanceof JSXElement) {
1058
+ const { nativeNode: n, applyRefs: a } = this.createElement(atom.jsxNode);
1059
+ nativeNode = n;
1060
+ applyRefs = a;
1054
1061
  }
1055
1062
  else {
1056
- const host = getContext();
1057
- const nativeNode = atom.jsxNode instanceof JSXElement ? this.createElement(atom.jsxNode) : this.createTextNode(atom.jsxNode);
1058
- atom.nativeNode = nativeNode;
1059
- if (host) {
1060
- this.nativeRenderer.appendChild(host, nativeNode);
1061
- }
1062
- else {
1063
- children.push(nativeNode);
1064
- }
1065
- if (atom.child) {
1066
- context.push(nativeNode);
1067
- atom = atom.child;
1068
- continue;
1069
- }
1063
+ nativeNode = this.createTextNode(atom.jsxNode);
1070
1064
  }
1071
- while (atom) {
1072
- if (atom.sibling) {
1073
- atom = atom.sibling;
1074
- break;
1075
- }
1076
- atom = atom.parent;
1077
- const isComponent = (atom === null || atom === void 0 ? void 0 : atom.jsxNode) instanceof Component;
1078
- if (isComponent) {
1079
- atom.jsxNode.rendered();
1080
- }
1081
- if (atom === stopAtom) {
1082
- break wrap;
1083
- }
1084
- if (isComponent) {
1085
- continue;
1065
+ atom.nativeNode = nativeNode;
1066
+ if (context.isParent) {
1067
+ this.nativeRenderer.prependChild(context.host, nativeNode);
1068
+ }
1069
+ else {
1070
+ this.nativeRenderer.insertAfter(nativeNode, context.host);
1071
+ }
1072
+ if (atom.jsxNode instanceof JSXElement) {
1073
+ const childContext = {
1074
+ isParent: true,
1075
+ host: nativeNode
1076
+ };
1077
+ let child = atom.child;
1078
+ while (child) {
1079
+ this.buildView(child, childContext);
1080
+ child = child.sibling;
1086
1081
  }
1087
- context.pop();
1082
+ }
1083
+ context.host = nativeNode;
1084
+ context.isParent = false;
1085
+ if (applyRefs) {
1086
+ applyRefs();
1088
1087
  }
1089
1088
  }
1090
- return children;
1091
1089
  }
1092
- componentRender(component, parent) {
1090
+ componentRender(component, from) {
1093
1091
  const { template, render } = component.init();
1094
1092
  if (template) {
1095
- this.linkTemplate(template, component, parent);
1093
+ this.linkTemplate(template, component, from);
1096
1094
  }
1097
1095
  this.componentAtomCaches.set(component, {
1098
1096
  render,
1099
- atom: parent
1097
+ atom: from
1100
1098
  });
1101
- return parent;
1099
+ return from;
1102
1100
  }
1103
1101
  createChainByComponentFactory(context, factory, parent) {
1104
1102
  const component = factory.createInstance(context);
@@ -1154,25 +1152,27 @@ let Renderer = class Renderer {
1154
1152
  createElement(vNode) {
1155
1153
  const nativeNode = this.nativeRenderer.createElement(vNode.name);
1156
1154
  const props = vNode.props;
1157
- if (props) {
1158
- let bindingRefs;
1159
- props.attrs.forEach((value, key) => {
1160
- if (key === refKey) {
1161
- bindingRefs = value;
1162
- return;
1163
- }
1164
- this.nativeRenderer.setProperty(nativeNode, key, value);
1165
- });
1166
- props.styles.forEach((value, key) => {
1167
- this.nativeRenderer.setStyle(nativeNode, key, value);
1168
- });
1169
- props.classes.forEach(k => this.nativeRenderer.addClass(nativeNode, k));
1170
- Object.keys(props.listeners).forEach(type => {
1171
- this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1172
- });
1173
- this.applyRefs(bindingRefs, nativeNode, true);
1174
- }
1175
- return nativeNode;
1155
+ let bindingRefs;
1156
+ props.attrs.forEach((value, key) => {
1157
+ if (key === refKey) {
1158
+ bindingRefs = value;
1159
+ return;
1160
+ }
1161
+ this.nativeRenderer.setProperty(nativeNode, key, value);
1162
+ });
1163
+ props.styles.forEach((value, key) => {
1164
+ this.nativeRenderer.setStyle(nativeNode, key, value);
1165
+ });
1166
+ props.classes.forEach(k => this.nativeRenderer.addClass(nativeNode, k));
1167
+ Object.keys(props.listeners).forEach(type => {
1168
+ this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1169
+ });
1170
+ return {
1171
+ nativeNode,
1172
+ applyRefs: () => {
1173
+ this.applyRefs(bindingRefs, nativeNode, true);
1174
+ }
1175
+ };
1176
1176
  }
1177
1177
  createTextNode(child) {
1178
1178
  return this.nativeRenderer.createTextNode(child.text);
@@ -1180,7 +1180,7 @@ let Renderer = class Renderer {
1180
1180
  updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
1181
1181
  const { styleChanges, attrChanges, classesChanges, listenerChanges, isChanged } = getNodeChanges(newVNode, oldVNode);
1182
1182
  if (!isChanged) {
1183
- return;
1183
+ return null;
1184
1184
  }
1185
1185
  styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1186
1186
  styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
@@ -1208,8 +1208,10 @@ let Renderer = class Renderer {
1208
1208
  listenerChanges.add.forEach(i => {
1209
1209
  this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1210
1210
  });
1211
- this.applyRefs(unBindRefs, nativeNode, false);
1212
- this.applyRefs(bindRefs, nativeNode, true);
1211
+ return () => {
1212
+ this.applyRefs(unBindRefs, nativeNode, false);
1213
+ this.applyRefs(bindRefs, nativeNode, true);
1214
+ };
1213
1215
  }
1214
1216
  applyRefs(refs, nativeNode, binding) {
1215
1217
  refs = Array.isArray(refs) ? refs : [refs];
package/bundles/index.js CHANGED
@@ -48,20 +48,20 @@ const jsxErrorFn = makeError('JSX');
48
48
  const Fragment = function Fragment() {
49
49
  throw jsxErrorFn('Fragment does not support calling.');
50
50
  };
51
- function jsx(setup, config) {
51
+ function jsx(setup, config, key) {
52
52
  if (typeof setup === 'string') {
53
- return new JSXElement(setup, config);
53
+ return new JSXElement(setup, config, key);
54
54
  }
55
55
  return new JSXComponent(function (context) {
56
- return new Component(context, setup, config);
56
+ return new Component(context, setup, config, key);
57
57
  });
58
58
  }
59
- function jsxs(setup, config) {
59
+ function jsxs(setup, config, key) {
60
60
  if (typeof setup === 'string') {
61
- return new JSXElement(setup, config);
61
+ return new JSXElement(setup, config, key);
62
62
  }
63
63
  return new JSXComponent(function (context) {
64
- return new Component(context, setup, config);
64
+ return new Component(context, setup, config, key);
65
65
  });
66
66
  }
67
67
  class JSXText {
@@ -172,9 +172,10 @@ class Props {
172
172
  }
173
173
  }
174
174
  class JSXElement {
175
- constructor(name, config) {
175
+ constructor(name, config, key) {
176
176
  this.name = name;
177
177
  this.config = config;
178
+ this.key = key;
178
179
  this.props = new Props(config);
179
180
  }
180
181
  }
@@ -213,10 +214,11 @@ class Component extends di.ReflectiveInjector {
213
214
  get changed() {
214
215
  return this._changed;
215
216
  }
216
- constructor(context, setup, config) {
217
+ constructor(context, setup, config, key) {
217
218
  super(context, []);
218
219
  this.setup = setup;
219
220
  this.config = config;
221
+ this.key = key;
220
222
  this.destroyCallbacks = [];
221
223
  this.mountCallbacks = [];
222
224
  this.propsChangedCallbacks = [];
@@ -786,10 +788,10 @@ exports.Renderer = class Renderer {
786
788
  }
787
789
  render() {
788
790
  const { component, host } = this.rootComponentRef;
789
- const chain = new Atom(component, null);
790
- const children = this.buildView(chain);
791
- children.forEach(child => {
792
- this.nativeRenderer.appendChild(host, child);
791
+ const atom = new Atom(component, null);
792
+ this.buildView(atom, {
793
+ isParent: true,
794
+ host
793
795
  });
794
796
  }
795
797
  refresh() {
@@ -872,12 +874,17 @@ exports.Renderer = class Renderer {
872
874
  }
873
875
  diff(start, diffAtom, context) {
874
876
  const oldChildren = [];
877
+ let index = 0;
875
878
  while (diffAtom) {
876
- oldChildren.push(diffAtom);
879
+ oldChildren.push({
880
+ index,
881
+ atom: diffAtom
882
+ });
877
883
  diffAtom = diffAtom.sibling;
884
+ index++;
878
885
  }
879
886
  const commits = [];
880
- const addReuseCommit = (start, reusedAtom) => {
887
+ const addUpdateCommit = (start, reusedAtom) => {
881
888
  commits.push(() => {
882
889
  const isComponent = start.jsxNode instanceof Component;
883
890
  if (!isComponent) {
@@ -891,6 +898,10 @@ exports.Renderer = class Renderer {
891
898
  context.host = start.nativeNode;
892
899
  context.isParent = false;
893
900
  }
901
+ let applyRefs = null;
902
+ if (start.jsxNode instanceof JSXElement) {
903
+ applyRefs = this.updateNativeNodeProperties(start.jsxNode, reusedAtom.jsxNode, start.nativeNode);
904
+ }
894
905
  if (start.child) {
895
906
  const childContext = start.jsxNode instanceof JSXElement ? {
896
907
  host: start.nativeNode,
@@ -899,7 +910,14 @@ exports.Renderer = class Renderer {
899
910
  this.diff(start.child, reusedAtom.child, childContext);
900
911
  }
901
912
  else if (reusedAtom.child) {
902
- this.cleanView(reusedAtom.child, false);
913
+ let atom = reusedAtom.child;
914
+ while (atom) {
915
+ this.cleanView(atom, false);
916
+ atom = atom.sibling;
917
+ }
918
+ }
919
+ if (applyRefs) {
920
+ applyRefs();
903
921
  }
904
922
  if (isComponent) {
905
923
  start.jsxNode.rendered();
@@ -908,31 +926,23 @@ exports.Renderer = class Renderer {
908
926
  };
909
927
  const addCreateCommit = (start) => {
910
928
  commits.push(() => {
911
- const children = this.createViewByAtom(start);
912
- children.forEach(child => {
913
- if (context.isParent) {
914
- this.nativeRenderer.prependChild(context.host, child);
915
- }
916
- else {
917
- this.nativeRenderer.insertAfter(child, context.host);
918
- }
919
- context.host = child;
920
- context.isParent = false;
921
- });
929
+ this.buildView(start, context);
922
930
  });
923
931
  };
932
+ let i = 0;
924
933
  while (start && !start.nativeNode) {
925
- const reusedAtom = this.reuseAndUpdate(start, oldChildren);
934
+ const reusedAtom = this.reuseAndUpdate(start, i, oldChildren);
926
935
  if (reusedAtom) {
927
- addReuseCommit(start, reusedAtom);
936
+ addUpdateCommit(start, reusedAtom);
928
937
  }
929
938
  else {
930
939
  addCreateCommit(start);
931
940
  }
941
+ i++;
932
942
  start = start.sibling;
933
943
  }
934
- for (const atom of oldChildren) {
935
- this.cleanView(atom, false);
944
+ for (const item of oldChildren) {
945
+ this.cleanView(item.atom, false);
936
946
  }
937
947
  for (const commit of commits) {
938
948
  commit();
@@ -958,14 +968,25 @@ exports.Renderer = class Renderer {
958
968
  atom.jsxNode.destroy();
959
969
  }
960
970
  }
961
- reuseAndUpdate(start, oldChildren) {
971
+ reuseAndUpdate(start, lastIndex, oldChildren) {
972
+ let isReuse = false;
962
973
  for (let i = 0; i < oldChildren.length; i++) {
963
- const diffAtom = oldChildren[i];
974
+ const { atom: diffAtom, index: diffIndex } = oldChildren[i];
975
+ const key = start.jsxNode.key;
976
+ const diffKey = diffAtom.jsxNode.key;
977
+ if (key !== undefined && diffKey !== undefined) {
978
+ if (diffKey !== key) {
979
+ continue;
980
+ }
981
+ isReuse = lastIndex > diffIndex;
982
+ }
964
983
  if (start.jsxNode instanceof JSXElement) {
965
984
  if (diffAtom.jsxNode instanceof JSXElement && start.jsxNode.name === diffAtom.jsxNode.name) {
966
985
  const nativeNode = diffAtom.nativeNode;
986
+ if (isReuse) {
987
+ this.nativeRenderer.remove(nativeNode);
988
+ }
967
989
  start.nativeNode = nativeNode;
968
- this.updateNativeNodeProperties(start.jsxNode, diffAtom.jsxNode, nativeNode);
969
990
  oldChildren.splice(i, 1);
970
991
  return diffAtom;
971
992
  }
@@ -983,6 +1004,9 @@ exports.Renderer = class Renderer {
983
1004
  }
984
1005
  else if (diffAtom.jsxNode instanceof Component) {
985
1006
  if (start.jsxNode.setup === diffAtom.jsxNode.setup) {
1007
+ if (isReuse) {
1008
+ this.temporarilyRemove(diffAtom);
1009
+ }
986
1010
  const { isChanged } = getNodeChanges(start.jsxNode, diffAtom.jsxNode);
987
1011
  if (isChanged) {
988
1012
  diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
@@ -1006,100 +1030,74 @@ exports.Renderer = class Renderer {
1006
1030
  }
1007
1031
  return null;
1008
1032
  }
1009
- createViewByAtom(atom) {
1010
- if (atom.jsxNode instanceof JSXElement) {
1011
- const nativeNode = this.createElement(atom.jsxNode);
1012
- atom.nativeNode = nativeNode;
1013
- if (atom.child) {
1014
- const children = this.buildView(atom.child);
1015
- for (const child of children) {
1016
- this.nativeRenderer.appendChild(nativeNode, child);
1017
- }
1033
+ temporarilyRemove(atom) {
1034
+ let next = atom.child;
1035
+ while (next) {
1036
+ if (next.jsxNode instanceof Component) {
1037
+ this.temporarilyRemove(next);
1018
1038
  }
1019
- return [nativeNode];
1020
- }
1021
- else if (atom.jsxNode instanceof JSXText) {
1022
- const nativeNode = this.createTextNode(atom.jsxNode);
1023
- atom.nativeNode = nativeNode;
1024
- return [nativeNode];
1025
- }
1026
- const { template, render } = atom.jsxNode.init();
1027
- this.componentAtomCaches.set(atom.jsxNode, {
1028
- atom,
1029
- render
1030
- });
1031
- if (template) {
1032
- this.linkTemplate(template, atom.jsxNode, atom);
1033
- }
1034
- if (atom.child) {
1035
- return this.buildView(atom.child);
1039
+ else {
1040
+ this.nativeRenderer.remove(next.nativeNode);
1041
+ }
1042
+ next = next.sibling;
1036
1043
  }
1037
- return [];
1038
1044
  }
1039
- buildView(chain) {
1040
- const context = [];
1041
- const children = [];
1042
- function getContext() {
1043
- return context[context.length - 1];
1044
- }
1045
- let atom = chain;
1046
- const stopAtom = chain.parent;
1047
- wrap: while (atom) {
1048
- if (atom.jsxNode instanceof Component) {
1049
- this.componentRender(atom.jsxNode, atom);
1050
- if (atom.child) {
1051
- atom = atom.child;
1052
- continue;
1053
- }
1054
- atom.jsxNode.rendered();
1045
+ buildView(atom, context) {
1046
+ if (atom.jsxNode instanceof Component) {
1047
+ this.componentRender(atom.jsxNode, atom);
1048
+ let child = atom.child;
1049
+ while (child) {
1050
+ this.buildView(child, context);
1051
+ child = child.sibling;
1052
+ }
1053
+ atom.jsxNode.rendered();
1054
+ }
1055
+ else {
1056
+ let nativeNode;
1057
+ let applyRefs = null;
1058
+ if (atom.jsxNode instanceof JSXElement) {
1059
+ const { nativeNode: n, applyRefs: a } = this.createElement(atom.jsxNode);
1060
+ nativeNode = n;
1061
+ applyRefs = a;
1055
1062
  }
1056
1063
  else {
1057
- const host = getContext();
1058
- const nativeNode = atom.jsxNode instanceof JSXElement ? this.createElement(atom.jsxNode) : this.createTextNode(atom.jsxNode);
1059
- atom.nativeNode = nativeNode;
1060
- if (host) {
1061
- this.nativeRenderer.appendChild(host, nativeNode);
1062
- }
1063
- else {
1064
- children.push(nativeNode);
1065
- }
1066
- if (atom.child) {
1067
- context.push(nativeNode);
1068
- atom = atom.child;
1069
- continue;
1070
- }
1064
+ nativeNode = this.createTextNode(atom.jsxNode);
1071
1065
  }
1072
- while (atom) {
1073
- if (atom.sibling) {
1074
- atom = atom.sibling;
1075
- break;
1076
- }
1077
- atom = atom.parent;
1078
- const isComponent = (atom === null || atom === void 0 ? void 0 : atom.jsxNode) instanceof Component;
1079
- if (isComponent) {
1080
- atom.jsxNode.rendered();
1081
- }
1082
- if (atom === stopAtom) {
1083
- break wrap;
1084
- }
1085
- if (isComponent) {
1086
- continue;
1066
+ atom.nativeNode = nativeNode;
1067
+ if (context.isParent) {
1068
+ this.nativeRenderer.prependChild(context.host, nativeNode);
1069
+ }
1070
+ else {
1071
+ this.nativeRenderer.insertAfter(nativeNode, context.host);
1072
+ }
1073
+ if (atom.jsxNode instanceof JSXElement) {
1074
+ const childContext = {
1075
+ isParent: true,
1076
+ host: nativeNode
1077
+ };
1078
+ let child = atom.child;
1079
+ while (child) {
1080
+ this.buildView(child, childContext);
1081
+ child = child.sibling;
1087
1082
  }
1088
- context.pop();
1083
+ }
1084
+ context.host = nativeNode;
1085
+ context.isParent = false;
1086
+ if (applyRefs) {
1087
+ applyRefs();
1089
1088
  }
1090
1089
  }
1091
- return children;
1092
1090
  }
1093
- componentRender(component, parent) {
1091
+ componentRender(component, from) {
1094
1092
  const { template, render } = component.init();
1095
1093
  if (template) {
1096
- this.linkTemplate(template, component, parent);
1094
+ this.linkTemplate(template, component, from);
1097
1095
  }
1098
1096
  this.componentAtomCaches.set(component, {
1099
1097
  render,
1100
- atom: parent
1098
+ atom: from
1101
1099
  });
1102
- return parent;
1100
+ return from;
1103
1101
  }
1104
1102
  createChainByComponentFactory(context, factory, parent) {
1105
1103
  const component = factory.createInstance(context);
@@ -1155,25 +1153,27 @@ exports.Renderer = class Renderer {
1155
1153
  createElement(vNode) {
1156
1154
  const nativeNode = this.nativeRenderer.createElement(vNode.name);
1157
1155
  const props = vNode.props;
1158
- if (props) {
1159
- let bindingRefs;
1160
- props.attrs.forEach((value, key) => {
1161
- if (key === refKey) {
1162
- bindingRefs = value;
1163
- return;
1164
- }
1165
- this.nativeRenderer.setProperty(nativeNode, key, value);
1166
- });
1167
- props.styles.forEach((value, key) => {
1168
- this.nativeRenderer.setStyle(nativeNode, key, value);
1169
- });
1170
- props.classes.forEach(k => this.nativeRenderer.addClass(nativeNode, k));
1171
- Object.keys(props.listeners).forEach(type => {
1172
- this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1173
- });
1174
- this.applyRefs(bindingRefs, nativeNode, true);
1175
- }
1176
- return nativeNode;
1156
+ let bindingRefs;
1157
+ props.attrs.forEach((value, key) => {
1158
+ if (key === refKey) {
1159
+ bindingRefs = value;
1160
+ return;
1161
+ }
1162
+ this.nativeRenderer.setProperty(nativeNode, key, value);
1163
+ });
1164
+ props.styles.forEach((value, key) => {
1165
+ this.nativeRenderer.setStyle(nativeNode, key, value);
1166
+ });
1167
+ props.classes.forEach(k => this.nativeRenderer.addClass(nativeNode, k));
1168
+ Object.keys(props.listeners).forEach(type => {
1169
+ this.nativeRenderer.listen(nativeNode, type, props.listeners[type]);
1170
+ });
1171
+ return {
1172
+ nativeNode,
1173
+ applyRefs: () => {
1174
+ this.applyRefs(bindingRefs, nativeNode, true);
1175
+ }
1176
+ };
1177
1177
  }
1178
1178
  createTextNode(child) {
1179
1179
  return this.nativeRenderer.createTextNode(child.text);
@@ -1181,7 +1181,7 @@ exports.Renderer = class Renderer {
1181
1181
  updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
1182
1182
  const { styleChanges, attrChanges, classesChanges, listenerChanges, isChanged } = getNodeChanges(newVNode, oldVNode);
1183
1183
  if (!isChanged) {
1184
- return;
1184
+ return null;
1185
1185
  }
1186
1186
  styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
1187
1187
  styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
@@ -1209,8 +1209,10 @@ exports.Renderer = class Renderer {
1209
1209
  listenerChanges.add.forEach(i => {
1210
1210
  this.nativeRenderer.listen(nativeNode, i[0], i[1]);
1211
1211
  });
1212
- this.applyRefs(unBindRefs, nativeNode, false);
1213
- this.applyRefs(bindRefs, nativeNode, true);
1212
+ return () => {
1213
+ this.applyRefs(unBindRefs, nativeNode, false);
1214
+ this.applyRefs(bindRefs, nativeNode, true);
1215
+ };
1214
1216
  }
1215
1217
  applyRefs(refs, nativeNode, binding) {
1216
1218
  refs = Array.isArray(refs) ? refs : [refs];
@@ -1,5 +1,5 @@
1
1
  import { Provider, ReflectiveInjector, AbstractType, Type, InjectionToken, InjectFlags, Injector } from '@tanbo/di';
2
- import { JSXProps, JSXElement, Props } from './jsx-element';
2
+ import { JSXProps, JSXElement, Props, Key } from './jsx-element';
3
3
  export declare class JSXComponent {
4
4
  createInstance: (injector: Component) => Component;
5
5
  constructor(createInstance: (injector: Component) => Component);
@@ -14,6 +14,7 @@ export interface ComponentSetup<T extends JSXProps<any> = JSXProps<any>> {
14
14
  export declare class Component extends ReflectiveInjector {
15
15
  setup: ComponentSetup;
16
16
  config?: JSXProps<any> | null | undefined;
17
+ key?: Key | undefined;
17
18
  destroyCallbacks: LifeCycleCallback[];
18
19
  mountCallbacks: LifeCycleCallback[];
19
20
  propsChangedCallbacks: PropsChangedCallback<any>[];
@@ -27,7 +28,7 @@ export declare class Component extends ReflectiveInjector {
27
28
  private updatedDestroyCallbacks;
28
29
  private propsChangedDestroyCallbacks;
29
30
  private isFirstRending;
30
- constructor(context: Injector, setup: ComponentSetup, config?: JSXProps<any> | null | undefined);
31
+ constructor(context: Injector, setup: ComponentSetup, config?: JSXProps<any> | null | undefined, key?: Key | undefined);
31
32
  addProvide<T>(providers: Provider<T> | Provider<T>[]): void;
32
33
  init(): {
33
34
  template: JSXTemplate;
@@ -6,10 +6,11 @@ export interface JSXProps<T = JSXChildNode | JSXChildNode[]> {
6
6
  [key: symbol]: any;
7
7
  }
8
8
  export declare const Fragment: () => never;
9
- export declare function jsx<T extends JSXChildNode>(name: string, config?: JSXProps<T> | null): JSXElement;
10
- export declare function jsx<T extends JSXChildNode>(setup: ComponentSetup, config?: JSXProps<T> | null): JSXComponent;
11
- export declare function jsxs<T extends JSXChildNode[]>(name: string, config?: JSXProps<T> | null): JSXElement;
12
- export declare function jsxs<T extends JSXChildNode[]>(setup: ComponentSetup, config?: JSXProps<T> | null): JSXComponent;
9
+ export type Key = number | string;
10
+ export declare function jsx<T extends JSXChildNode>(name: string, config?: JSXProps<T> | null, key?: Key): JSXElement;
11
+ export declare function jsx<T extends JSXChildNode>(setup: ComponentSetup, config?: JSXProps<T> | null, key?: Key): JSXComponent;
12
+ export declare function jsxs<T extends JSXChildNode[]>(name: string, config?: JSXProps<T> | null, key?: Key): JSXElement;
13
+ export declare function jsxs<T extends JSXChildNode[]>(setup: ComponentSetup, config?: JSXProps<T> | null, key?: Key): JSXComponent;
13
14
  export interface VElementListeners {
14
15
  [listenKey: string]: <T extends Event>(ev: T) => any;
15
16
  }
@@ -30,6 +31,7 @@ export declare class Props {
30
31
  export declare class JSXElement {
31
32
  name: string;
32
33
  config?: JSXProps<any> | null | undefined;
34
+ key?: Key | undefined;
33
35
  props: Props;
34
- constructor(name: string, config?: JSXProps<any> | null | undefined);
36
+ constructor(name: string, config?: JSXProps<any> | null | undefined, key?: Key | undefined);
35
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "0.0.1-alpha.5",
3
+ "version": "0.0.1-alpha.7",
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",
@@ -37,5 +37,5 @@
37
37
  "bugs": {
38
38
  "url": "https://github.com/viewfly/viewfly.git/issues"
39
39
  },
40
- "gitHead": "135aeda546b83c7947e888dfe40860858123b6fc"
40
+ "gitHead": "b4aa728ce10f6aaca2bb2e242c7b8b8f8befbfec"
41
41
  }