@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.
- package/bundles/foundation/renderer.d.ts +1 -1
- package/bundles/index.esm.js +135 -133
- package/bundles/index.js +135 -133
- package/bundles/model/component.d.ts +3 -2
- package/bundles/model/jsx-element.d.ts +7 -5
- package/package.json +2 -2
package/bundles/index.esm.js
CHANGED
|
@@ -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
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
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(
|
|
878
|
+
oldChildren.push({
|
|
879
|
+
index,
|
|
880
|
+
atom: diffAtom
|
|
881
|
+
});
|
|
876
882
|
diffAtom = diffAtom.sibling;
|
|
883
|
+
index++;
|
|
877
884
|
}
|
|
878
885
|
const commits = [];
|
|
879
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
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
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
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(
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
}
|
|
1053
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
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
|
-
|
|
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,
|
|
1090
|
+
componentRender(component, from) {
|
|
1093
1091
|
const { template, render } = component.init();
|
|
1094
1092
|
if (template) {
|
|
1095
|
-
this.linkTemplate(template, component,
|
|
1093
|
+
this.linkTemplate(template, component, from);
|
|
1096
1094
|
}
|
|
1097
1095
|
this.componentAtomCaches.set(component, {
|
|
1098
1096
|
render,
|
|
1099
|
-
atom:
|
|
1097
|
+
atom: from
|
|
1100
1098
|
});
|
|
1101
|
-
return
|
|
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
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
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
|
-
|
|
1212
|
-
|
|
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
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
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(
|
|
879
|
+
oldChildren.push({
|
|
880
|
+
index,
|
|
881
|
+
atom: diffAtom
|
|
882
|
+
});
|
|
877
883
|
diffAtom = diffAtom.sibling;
|
|
884
|
+
index++;
|
|
878
885
|
}
|
|
879
886
|
const commits = [];
|
|
880
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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(
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
}
|
|
1054
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
|
|
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,
|
|
1091
|
+
componentRender(component, from) {
|
|
1094
1092
|
const { template, render } = component.init();
|
|
1095
1093
|
if (template) {
|
|
1096
|
-
this.linkTemplate(template, component,
|
|
1094
|
+
this.linkTemplate(template, component, from);
|
|
1097
1095
|
}
|
|
1098
1096
|
this.componentAtomCaches.set(component, {
|
|
1099
1097
|
render,
|
|
1100
|
-
atom:
|
|
1098
|
+
atom: from
|
|
1101
1099
|
});
|
|
1102
|
-
return
|
|
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
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
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
|
-
|
|
1213
|
-
|
|
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
|
|
10
|
-
export declare function jsx<T extends JSXChildNode>(
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function jsxs<T extends JSXChildNode[]>(
|
|
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.
|
|
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": "
|
|
40
|
+
"gitHead": "b4aa728ce10f6aaca2bb2e242c7b8b8f8befbfec"
|
|
41
41
|
}
|