@viewfly/core 0.0.1-alpha.6 → 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 +130 -132
- package/bundles/index.js +130 -132
- 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,
|
|
@@ -904,6 +915,9 @@ let Renderer = class Renderer {
|
|
|
904
915
|
atom = atom.sibling;
|
|
905
916
|
}
|
|
906
917
|
}
|
|
918
|
+
if (applyRefs) {
|
|
919
|
+
applyRefs();
|
|
920
|
+
}
|
|
907
921
|
if (isComponent) {
|
|
908
922
|
start.jsxNode.rendered();
|
|
909
923
|
}
|
|
@@ -911,31 +925,23 @@ let Renderer = class Renderer {
|
|
|
911
925
|
};
|
|
912
926
|
const addCreateCommit = (start) => {
|
|
913
927
|
commits.push(() => {
|
|
914
|
-
|
|
915
|
-
children.forEach(child => {
|
|
916
|
-
if (context.isParent) {
|
|
917
|
-
this.nativeRenderer.prependChild(context.host, child);
|
|
918
|
-
}
|
|
919
|
-
else {
|
|
920
|
-
this.nativeRenderer.insertAfter(child, context.host);
|
|
921
|
-
}
|
|
922
|
-
context.host = child;
|
|
923
|
-
context.isParent = false;
|
|
924
|
-
});
|
|
928
|
+
this.buildView(start, context);
|
|
925
929
|
});
|
|
926
930
|
};
|
|
931
|
+
let i = 0;
|
|
927
932
|
while (start && !start.nativeNode) {
|
|
928
|
-
const reusedAtom = this.reuseAndUpdate(start, oldChildren);
|
|
933
|
+
const reusedAtom = this.reuseAndUpdate(start, i, oldChildren);
|
|
929
934
|
if (reusedAtom) {
|
|
930
|
-
|
|
935
|
+
addUpdateCommit(start, reusedAtom);
|
|
931
936
|
}
|
|
932
937
|
else {
|
|
933
938
|
addCreateCommit(start);
|
|
934
939
|
}
|
|
940
|
+
i++;
|
|
935
941
|
start = start.sibling;
|
|
936
942
|
}
|
|
937
|
-
for (const
|
|
938
|
-
this.cleanView(atom, false);
|
|
943
|
+
for (const item of oldChildren) {
|
|
944
|
+
this.cleanView(item.atom, false);
|
|
939
945
|
}
|
|
940
946
|
for (const commit of commits) {
|
|
941
947
|
commit();
|
|
@@ -961,14 +967,25 @@ let Renderer = class Renderer {
|
|
|
961
967
|
atom.jsxNode.destroy();
|
|
962
968
|
}
|
|
963
969
|
}
|
|
964
|
-
reuseAndUpdate(start, oldChildren) {
|
|
970
|
+
reuseAndUpdate(start, lastIndex, oldChildren) {
|
|
971
|
+
let isReuse = false;
|
|
965
972
|
for (let i = 0; i < oldChildren.length; i++) {
|
|
966
|
-
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
|
+
}
|
|
967
982
|
if (start.jsxNode instanceof JSXElement) {
|
|
968
983
|
if (diffAtom.jsxNode instanceof JSXElement && start.jsxNode.name === diffAtom.jsxNode.name) {
|
|
969
984
|
const nativeNode = diffAtom.nativeNode;
|
|
985
|
+
if (isReuse) {
|
|
986
|
+
this.nativeRenderer.remove(nativeNode);
|
|
987
|
+
}
|
|
970
988
|
start.nativeNode = nativeNode;
|
|
971
|
-
this.updateNativeNodeProperties(start.jsxNode, diffAtom.jsxNode, nativeNode);
|
|
972
989
|
oldChildren.splice(i, 1);
|
|
973
990
|
return diffAtom;
|
|
974
991
|
}
|
|
@@ -986,6 +1003,9 @@ let Renderer = class Renderer {
|
|
|
986
1003
|
}
|
|
987
1004
|
else if (diffAtom.jsxNode instanceof Component) {
|
|
988
1005
|
if (start.jsxNode.setup === diffAtom.jsxNode.setup) {
|
|
1006
|
+
if (isReuse) {
|
|
1007
|
+
this.temporarilyRemove(diffAtom);
|
|
1008
|
+
}
|
|
989
1009
|
const { isChanged } = getNodeChanges(start.jsxNode, diffAtom.jsxNode);
|
|
990
1010
|
if (isChanged) {
|
|
991
1011
|
diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
|
|
@@ -1009,100 +1029,74 @@ let Renderer = class Renderer {
|
|
|
1009
1029
|
}
|
|
1010
1030
|
return null;
|
|
1011
1031
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
const children = this.buildView(atom.child);
|
|
1018
|
-
for (const child of children) {
|
|
1019
|
-
this.nativeRenderer.appendChild(nativeNode, child);
|
|
1020
|
-
}
|
|
1032
|
+
temporarilyRemove(atom) {
|
|
1033
|
+
let next = atom.child;
|
|
1034
|
+
while (next) {
|
|
1035
|
+
if (next.jsxNode instanceof Component) {
|
|
1036
|
+
this.temporarilyRemove(next);
|
|
1021
1037
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
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);
|
|
1038
|
+
else {
|
|
1039
|
+
this.nativeRenderer.remove(next.nativeNode);
|
|
1040
|
+
}
|
|
1041
|
+
next = next.sibling;
|
|
1039
1042
|
}
|
|
1040
|
-
return [];
|
|
1041
1043
|
}
|
|
1042
|
-
buildView(
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
|
|
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;
|
|
1058
1061
|
}
|
|
1059
1062
|
else {
|
|
1060
|
-
|
|
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
|
-
}
|
|
1063
|
+
nativeNode = this.createTextNode(atom.jsxNode);
|
|
1074
1064
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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;
|
|
1090
1081
|
}
|
|
1091
|
-
|
|
1082
|
+
}
|
|
1083
|
+
context.host = nativeNode;
|
|
1084
|
+
context.isParent = false;
|
|
1085
|
+
if (applyRefs) {
|
|
1086
|
+
applyRefs();
|
|
1092
1087
|
}
|
|
1093
1088
|
}
|
|
1094
|
-
return children;
|
|
1095
1089
|
}
|
|
1096
|
-
componentRender(component,
|
|
1090
|
+
componentRender(component, from) {
|
|
1097
1091
|
const { template, render } = component.init();
|
|
1098
1092
|
if (template) {
|
|
1099
|
-
this.linkTemplate(template, component,
|
|
1093
|
+
this.linkTemplate(template, component, from);
|
|
1100
1094
|
}
|
|
1101
1095
|
this.componentAtomCaches.set(component, {
|
|
1102
1096
|
render,
|
|
1103
|
-
atom:
|
|
1097
|
+
atom: from
|
|
1104
1098
|
});
|
|
1105
|
-
return
|
|
1099
|
+
return from;
|
|
1106
1100
|
}
|
|
1107
1101
|
createChainByComponentFactory(context, factory, parent) {
|
|
1108
1102
|
const component = factory.createInstance(context);
|
|
@@ -1158,25 +1152,27 @@ let Renderer = class Renderer {
|
|
|
1158
1152
|
createElement(vNode) {
|
|
1159
1153
|
const nativeNode = this.nativeRenderer.createElement(vNode.name);
|
|
1160
1154
|
const props = vNode.props;
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
+
};
|
|
1180
1176
|
}
|
|
1181
1177
|
createTextNode(child) {
|
|
1182
1178
|
return this.nativeRenderer.createTextNode(child.text);
|
|
@@ -1184,7 +1180,7 @@ let Renderer = class Renderer {
|
|
|
1184
1180
|
updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
|
|
1185
1181
|
const { styleChanges, attrChanges, classesChanges, listenerChanges, isChanged } = getNodeChanges(newVNode, oldVNode);
|
|
1186
1182
|
if (!isChanged) {
|
|
1187
|
-
return;
|
|
1183
|
+
return null;
|
|
1188
1184
|
}
|
|
1189
1185
|
styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
|
|
1190
1186
|
styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
|
|
@@ -1212,8 +1208,10 @@ let Renderer = class Renderer {
|
|
|
1212
1208
|
listenerChanges.add.forEach(i => {
|
|
1213
1209
|
this.nativeRenderer.listen(nativeNode, i[0], i[1]);
|
|
1214
1210
|
});
|
|
1215
|
-
|
|
1216
|
-
|
|
1211
|
+
return () => {
|
|
1212
|
+
this.applyRefs(unBindRefs, nativeNode, false);
|
|
1213
|
+
this.applyRefs(bindRefs, nativeNode, true);
|
|
1214
|
+
};
|
|
1217
1215
|
}
|
|
1218
1216
|
applyRefs(refs, nativeNode, binding) {
|
|
1219
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,
|
|
@@ -905,6 +916,9 @@ exports.Renderer = class Renderer {
|
|
|
905
916
|
atom = atom.sibling;
|
|
906
917
|
}
|
|
907
918
|
}
|
|
919
|
+
if (applyRefs) {
|
|
920
|
+
applyRefs();
|
|
921
|
+
}
|
|
908
922
|
if (isComponent) {
|
|
909
923
|
start.jsxNode.rendered();
|
|
910
924
|
}
|
|
@@ -912,31 +926,23 @@ exports.Renderer = class Renderer {
|
|
|
912
926
|
};
|
|
913
927
|
const addCreateCommit = (start) => {
|
|
914
928
|
commits.push(() => {
|
|
915
|
-
|
|
916
|
-
children.forEach(child => {
|
|
917
|
-
if (context.isParent) {
|
|
918
|
-
this.nativeRenderer.prependChild(context.host, child);
|
|
919
|
-
}
|
|
920
|
-
else {
|
|
921
|
-
this.nativeRenderer.insertAfter(child, context.host);
|
|
922
|
-
}
|
|
923
|
-
context.host = child;
|
|
924
|
-
context.isParent = false;
|
|
925
|
-
});
|
|
929
|
+
this.buildView(start, context);
|
|
926
930
|
});
|
|
927
931
|
};
|
|
932
|
+
let i = 0;
|
|
928
933
|
while (start && !start.nativeNode) {
|
|
929
|
-
const reusedAtom = this.reuseAndUpdate(start, oldChildren);
|
|
934
|
+
const reusedAtom = this.reuseAndUpdate(start, i, oldChildren);
|
|
930
935
|
if (reusedAtom) {
|
|
931
|
-
|
|
936
|
+
addUpdateCommit(start, reusedAtom);
|
|
932
937
|
}
|
|
933
938
|
else {
|
|
934
939
|
addCreateCommit(start);
|
|
935
940
|
}
|
|
941
|
+
i++;
|
|
936
942
|
start = start.sibling;
|
|
937
943
|
}
|
|
938
|
-
for (const
|
|
939
|
-
this.cleanView(atom, false);
|
|
944
|
+
for (const item of oldChildren) {
|
|
945
|
+
this.cleanView(item.atom, false);
|
|
940
946
|
}
|
|
941
947
|
for (const commit of commits) {
|
|
942
948
|
commit();
|
|
@@ -962,14 +968,25 @@ exports.Renderer = class Renderer {
|
|
|
962
968
|
atom.jsxNode.destroy();
|
|
963
969
|
}
|
|
964
970
|
}
|
|
965
|
-
reuseAndUpdate(start, oldChildren) {
|
|
971
|
+
reuseAndUpdate(start, lastIndex, oldChildren) {
|
|
972
|
+
let isReuse = false;
|
|
966
973
|
for (let i = 0; i < oldChildren.length; i++) {
|
|
967
|
-
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
|
+
}
|
|
968
983
|
if (start.jsxNode instanceof JSXElement) {
|
|
969
984
|
if (diffAtom.jsxNode instanceof JSXElement && start.jsxNode.name === diffAtom.jsxNode.name) {
|
|
970
985
|
const nativeNode = diffAtom.nativeNode;
|
|
986
|
+
if (isReuse) {
|
|
987
|
+
this.nativeRenderer.remove(nativeNode);
|
|
988
|
+
}
|
|
971
989
|
start.nativeNode = nativeNode;
|
|
972
|
-
this.updateNativeNodeProperties(start.jsxNode, diffAtom.jsxNode, nativeNode);
|
|
973
990
|
oldChildren.splice(i, 1);
|
|
974
991
|
return diffAtom;
|
|
975
992
|
}
|
|
@@ -987,6 +1004,9 @@ exports.Renderer = class Renderer {
|
|
|
987
1004
|
}
|
|
988
1005
|
else if (diffAtom.jsxNode instanceof Component) {
|
|
989
1006
|
if (start.jsxNode.setup === diffAtom.jsxNode.setup) {
|
|
1007
|
+
if (isReuse) {
|
|
1008
|
+
this.temporarilyRemove(diffAtom);
|
|
1009
|
+
}
|
|
990
1010
|
const { isChanged } = getNodeChanges(start.jsxNode, diffAtom.jsxNode);
|
|
991
1011
|
if (isChanged) {
|
|
992
1012
|
diffAtom.jsxNode.invokePropsChangedHooks(start.jsxNode.config);
|
|
@@ -1010,100 +1030,74 @@ exports.Renderer = class Renderer {
|
|
|
1010
1030
|
}
|
|
1011
1031
|
return null;
|
|
1012
1032
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
const children = this.buildView(atom.child);
|
|
1019
|
-
for (const child of children) {
|
|
1020
|
-
this.nativeRenderer.appendChild(nativeNode, child);
|
|
1021
|
-
}
|
|
1033
|
+
temporarilyRemove(atom) {
|
|
1034
|
+
let next = atom.child;
|
|
1035
|
+
while (next) {
|
|
1036
|
+
if (next.jsxNode instanceof Component) {
|
|
1037
|
+
this.temporarilyRemove(next);
|
|
1022
1038
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
atom.nativeNode = nativeNode;
|
|
1028
|
-
return [nativeNode];
|
|
1029
|
-
}
|
|
1030
|
-
const { template, render } = atom.jsxNode.init();
|
|
1031
|
-
this.componentAtomCaches.set(atom.jsxNode, {
|
|
1032
|
-
atom,
|
|
1033
|
-
render
|
|
1034
|
-
});
|
|
1035
|
-
if (template) {
|
|
1036
|
-
this.linkTemplate(template, atom.jsxNode, atom);
|
|
1037
|
-
}
|
|
1038
|
-
if (atom.child) {
|
|
1039
|
-
return this.buildView(atom.child);
|
|
1039
|
+
else {
|
|
1040
|
+
this.nativeRenderer.remove(next.nativeNode);
|
|
1041
|
+
}
|
|
1042
|
+
next = next.sibling;
|
|
1040
1043
|
}
|
|
1041
|
-
return [];
|
|
1042
1044
|
}
|
|
1043
|
-
buildView(
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
|
|
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;
|
|
1059
1062
|
}
|
|
1060
1063
|
else {
|
|
1061
|
-
|
|
1062
|
-
const nativeNode = atom.jsxNode instanceof JSXElement ? this.createElement(atom.jsxNode) : this.createTextNode(atom.jsxNode);
|
|
1063
|
-
atom.nativeNode = nativeNode;
|
|
1064
|
-
if (host) {
|
|
1065
|
-
this.nativeRenderer.appendChild(host, nativeNode);
|
|
1066
|
-
}
|
|
1067
|
-
else {
|
|
1068
|
-
children.push(nativeNode);
|
|
1069
|
-
}
|
|
1070
|
-
if (atom.child) {
|
|
1071
|
-
context.push(nativeNode);
|
|
1072
|
-
atom = atom.child;
|
|
1073
|
-
continue;
|
|
1074
|
-
}
|
|
1064
|
+
nativeNode = this.createTextNode(atom.jsxNode);
|
|
1075
1065
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
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;
|
|
1091
1082
|
}
|
|
1092
|
-
|
|
1083
|
+
}
|
|
1084
|
+
context.host = nativeNode;
|
|
1085
|
+
context.isParent = false;
|
|
1086
|
+
if (applyRefs) {
|
|
1087
|
+
applyRefs();
|
|
1093
1088
|
}
|
|
1094
1089
|
}
|
|
1095
|
-
return children;
|
|
1096
1090
|
}
|
|
1097
|
-
componentRender(component,
|
|
1091
|
+
componentRender(component, from) {
|
|
1098
1092
|
const { template, render } = component.init();
|
|
1099
1093
|
if (template) {
|
|
1100
|
-
this.linkTemplate(template, component,
|
|
1094
|
+
this.linkTemplate(template, component, from);
|
|
1101
1095
|
}
|
|
1102
1096
|
this.componentAtomCaches.set(component, {
|
|
1103
1097
|
render,
|
|
1104
|
-
atom:
|
|
1098
|
+
atom: from
|
|
1105
1099
|
});
|
|
1106
|
-
return
|
|
1100
|
+
return from;
|
|
1107
1101
|
}
|
|
1108
1102
|
createChainByComponentFactory(context, factory, parent) {
|
|
1109
1103
|
const component = factory.createInstance(context);
|
|
@@ -1159,25 +1153,27 @@ exports.Renderer = class Renderer {
|
|
|
1159
1153
|
createElement(vNode) {
|
|
1160
1154
|
const nativeNode = this.nativeRenderer.createElement(vNode.name);
|
|
1161
1155
|
const props = vNode.props;
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
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
|
+
};
|
|
1181
1177
|
}
|
|
1182
1178
|
createTextNode(child) {
|
|
1183
1179
|
return this.nativeRenderer.createTextNode(child.text);
|
|
@@ -1185,7 +1181,7 @@ exports.Renderer = class Renderer {
|
|
|
1185
1181
|
updateNativeNodeProperties(newVNode, oldVNode, nativeNode) {
|
|
1186
1182
|
const { styleChanges, attrChanges, classesChanges, listenerChanges, isChanged } = getNodeChanges(newVNode, oldVNode);
|
|
1187
1183
|
if (!isChanged) {
|
|
1188
|
-
return;
|
|
1184
|
+
return null;
|
|
1189
1185
|
}
|
|
1190
1186
|
styleChanges.remove.forEach(i => this.nativeRenderer.removeStyle(nativeNode, i[0]));
|
|
1191
1187
|
styleChanges.set.forEach(i => this.nativeRenderer.setStyle(nativeNode, i[0], i[1]));
|
|
@@ -1213,8 +1209,10 @@ exports.Renderer = class Renderer {
|
|
|
1213
1209
|
listenerChanges.add.forEach(i => {
|
|
1214
1210
|
this.nativeRenderer.listen(nativeNode, i[0], i[1]);
|
|
1215
1211
|
});
|
|
1216
|
-
|
|
1217
|
-
|
|
1212
|
+
return () => {
|
|
1213
|
+
this.applyRefs(unBindRefs, nativeNode, false);
|
|
1214
|
+
this.applyRefs(bindRefs, nativeNode, true);
|
|
1215
|
+
};
|
|
1218
1216
|
}
|
|
1219
1217
|
applyRefs(refs, nativeNode, binding) {
|
|
1220
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
|
}
|