@viewfly/core 0.0.29 → 0.0.30
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/_utils.d.ts +7 -1
- package/bundles/foundation/component.d.ts +15 -4
- package/bundles/foundation/jsx-element.d.ts +13 -28
- package/bundles/foundation/renderer.d.ts +1 -2
- package/bundles/foundation/root.component.d.ts +5 -4
- package/bundles/index.esm.js +222 -170
- package/bundles/index.js +222 -170
- package/bundles/viewfly.d.ts +2 -1
- package/package.json +2 -2
package/bundles/index.esm.js
CHANGED
|
@@ -567,6 +567,23 @@ function getObjectChanges(newProps, oldProps) {
|
|
|
567
567
|
});
|
|
568
568
|
return changes;
|
|
569
569
|
}
|
|
570
|
+
function getArrayChanges(left, right) {
|
|
571
|
+
const changes = {
|
|
572
|
+
add: [],
|
|
573
|
+
remove: []
|
|
574
|
+
};
|
|
575
|
+
for (const i of left) {
|
|
576
|
+
if (!right.includes(i)) {
|
|
577
|
+
changes.remove.push(i);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
for (const i of right) {
|
|
581
|
+
if (!left.includes(i)) {
|
|
582
|
+
changes.add.push(i);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return changes;
|
|
586
|
+
}
|
|
570
587
|
function classToString(config) {
|
|
571
588
|
if (!config) {
|
|
572
589
|
return '';
|
|
@@ -630,23 +647,52 @@ function getSignalDepsContext() {
|
|
|
630
647
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
631
648
|
*/
|
|
632
649
|
class Component extends ReflectiveInjector {
|
|
633
|
-
|
|
634
|
-
|
|
650
|
+
get dirty() {
|
|
651
|
+
return this._dirty;
|
|
652
|
+
}
|
|
653
|
+
get changed() {
|
|
654
|
+
return this._changed;
|
|
655
|
+
}
|
|
656
|
+
constructor(parentComponent, type, props, key) {
|
|
657
|
+
super(parentComponent, [{
|
|
635
658
|
provide: Injector,
|
|
636
659
|
useFactory: () => this
|
|
637
660
|
}]);
|
|
638
|
-
this.
|
|
661
|
+
this.parentComponent = parentComponent;
|
|
662
|
+
this.type = type;
|
|
639
663
|
this.props = props;
|
|
640
664
|
this.key = key;
|
|
665
|
+
this.$$typeOf = this.type;
|
|
641
666
|
this.destroyCallbacks = [];
|
|
642
667
|
this.mountCallbacks = [];
|
|
643
668
|
this.propsChangedCallbacks = [];
|
|
644
669
|
this.updatedCallbacks = [];
|
|
670
|
+
this.changedSubComponents = new Set();
|
|
671
|
+
this._dirty = true;
|
|
672
|
+
this._changed = true;
|
|
645
673
|
this.updatedDestroyCallbacks = [];
|
|
646
674
|
this.propsChangedDestroyCallbacks = [];
|
|
647
675
|
this.isFirstRending = true;
|
|
676
|
+
}
|
|
677
|
+
markAsDirtied() {
|
|
678
|
+
this._dirty = true;
|
|
679
|
+
this.markAsChanged();
|
|
680
|
+
}
|
|
681
|
+
markAsChanged(changedComponent) {
|
|
682
|
+
if (changedComponent) {
|
|
683
|
+
this.changedSubComponents.add(changedComponent);
|
|
684
|
+
}
|
|
685
|
+
if (this._changed) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
this._changed = true;
|
|
689
|
+
if (this.parentComponent instanceof Component) {
|
|
690
|
+
this.parentComponent.markAsChanged(this);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
render() {
|
|
648
694
|
const self = this;
|
|
649
|
-
const proxiesProps = new Proxy(props, {
|
|
695
|
+
const proxiesProps = new Proxy(this.props, {
|
|
650
696
|
get(_, key) {
|
|
651
697
|
// 必须用 self,因为 props 会随着页面更新变更,使用 self 才能更新引用
|
|
652
698
|
return self.props[key];
|
|
@@ -661,10 +707,10 @@ class Component extends ReflectiveInjector {
|
|
|
661
707
|
});
|
|
662
708
|
componentSetupStack.push(this);
|
|
663
709
|
let isSetup = true;
|
|
664
|
-
const render = this.
|
|
710
|
+
const render = this.type(proxiesProps);
|
|
665
711
|
const isRenderFn = typeof render === 'function';
|
|
666
712
|
this.instance = isRenderFn ? { $render: render } : render;
|
|
667
|
-
this.refs = toRefs(props.ref);
|
|
713
|
+
this.refs = toRefs(this.props.ref);
|
|
668
714
|
this.mountCallbacks.push(() => {
|
|
669
715
|
for (const ref of this.refs) {
|
|
670
716
|
ref.bind(this.instance);
|
|
@@ -677,13 +723,11 @@ class Component extends ReflectiveInjector {
|
|
|
677
723
|
});
|
|
678
724
|
isSetup = false;
|
|
679
725
|
componentSetupStack.pop();
|
|
680
|
-
}
|
|
681
|
-
render() {
|
|
682
726
|
signalDepsStack.push([]);
|
|
683
727
|
let template = this.instance.$render();
|
|
684
728
|
const deps = signalDepsStack.pop();
|
|
685
|
-
this.unWatch = useEffect(deps, () => {
|
|
686
|
-
this.
|
|
729
|
+
this.unWatch = useEffect(Array.from(new Set(deps)), () => {
|
|
730
|
+
this.markAsDirtied();
|
|
687
731
|
});
|
|
688
732
|
this.template = template;
|
|
689
733
|
return template;
|
|
@@ -715,8 +759,8 @@ class Component extends ReflectiveInjector {
|
|
|
715
759
|
signalDepsStack.push([]);
|
|
716
760
|
this.template = this.instance.$render();
|
|
717
761
|
const deps = signalDepsStack.pop();
|
|
718
|
-
this.unWatch = useEffect(deps, () => {
|
|
719
|
-
this.
|
|
762
|
+
this.unWatch = useEffect(Array.from(new Set(deps)), () => {
|
|
763
|
+
this.markAsDirtied();
|
|
720
764
|
});
|
|
721
765
|
return this.template;
|
|
722
766
|
}
|
|
@@ -725,8 +769,10 @@ class Component extends ReflectiveInjector {
|
|
|
725
769
|
this.normalizedProviders.unshift(...providers.map(i => normalizeProvider(i)));
|
|
726
770
|
}
|
|
727
771
|
rendered() {
|
|
772
|
+
this.changedSubComponents.clear();
|
|
728
773
|
const is = this.isFirstRending;
|
|
729
774
|
this.isFirstRending = false;
|
|
775
|
+
this._dirty = this._changed = false;
|
|
730
776
|
if (is) {
|
|
731
777
|
this.invokeUpdatedHooks();
|
|
732
778
|
this.invokeMountHooks();
|
|
@@ -974,10 +1020,48 @@ function invokeDepFn(fn) {
|
|
|
974
1020
|
const data = fn();
|
|
975
1021
|
signalDepsStack.pop();
|
|
976
1022
|
return {
|
|
977
|
-
deps,
|
|
1023
|
+
deps: Array.from(new Set(deps)),
|
|
978
1024
|
data
|
|
979
1025
|
};
|
|
980
1026
|
}
|
|
1027
|
+
function listen(model, deps, callback, isContinue) {
|
|
1028
|
+
let isStop = false;
|
|
1029
|
+
const nextListen = () => {
|
|
1030
|
+
if (isStop) {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
isStop = true;
|
|
1034
|
+
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
1035
|
+
model.set(nextData);
|
|
1036
|
+
if (typeof isContinue === 'function' && isContinue(nextData) === false) {
|
|
1037
|
+
unListen();
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
const changes = getArrayChanges(deps, nextDeps);
|
|
1041
|
+
deps = deps.filter(i => {
|
|
1042
|
+
const has = changes.remove.includes(i);
|
|
1043
|
+
if (has) {
|
|
1044
|
+
i[depsKey].delete(nextListen);
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
return true;
|
|
1048
|
+
});
|
|
1049
|
+
for (const s of changes.add) {
|
|
1050
|
+
s[depsKey].add(nextListen);
|
|
1051
|
+
}
|
|
1052
|
+
deps.push(...changes.add);
|
|
1053
|
+
isStop = false;
|
|
1054
|
+
};
|
|
1055
|
+
const unListen = () => {
|
|
1056
|
+
for (const s of deps) {
|
|
1057
|
+
s[depsKey].delete(nextListen);
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
for (const s of deps) {
|
|
1061
|
+
s[depsKey].add(nextListen);
|
|
1062
|
+
}
|
|
1063
|
+
return unListen;
|
|
1064
|
+
}
|
|
981
1065
|
/**
|
|
982
1066
|
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
983
1067
|
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
@@ -989,29 +1073,10 @@ function useDerived(callback, isContinue) {
|
|
|
989
1073
|
let { data, deps } = invokeDepFn(callback);
|
|
990
1074
|
const signal = useSignal(data);
|
|
991
1075
|
const component = getSetupContext(false);
|
|
992
|
-
const
|
|
993
|
-
function listen(model, deps, callback, unListenRef, isContinue) {
|
|
994
|
-
const nextListen = () => {
|
|
995
|
-
unListenRef.unListen();
|
|
996
|
-
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
997
|
-
model.set(nextData);
|
|
998
|
-
if (typeof isContinue !== 'function' || isContinue(nextData) !== false) {
|
|
999
|
-
listen(model, nextDeps, callback, unListenRef, isContinue);
|
|
1000
|
-
}
|
|
1001
|
-
};
|
|
1002
|
-
unListenRef.unListen = () => {
|
|
1003
|
-
for (const s of deps) {
|
|
1004
|
-
s[depsKey].delete(nextListen);
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
1007
|
-
for (const s of deps) {
|
|
1008
|
-
s[depsKey].add(nextListen);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
listen(signal, deps, callback, unListenRef, isContinue);
|
|
1076
|
+
const unListen = listen(signal, deps, callback, isContinue);
|
|
1012
1077
|
if (component) {
|
|
1013
1078
|
component.destroyCallbacks.push(() => {
|
|
1014
|
-
|
|
1079
|
+
unListen();
|
|
1015
1080
|
});
|
|
1016
1081
|
}
|
|
1017
1082
|
return signal;
|
|
@@ -1084,25 +1149,23 @@ function Fragment(props) {
|
|
|
1084
1149
|
}
|
|
1085
1150
|
function jsx(setup, props, key) {
|
|
1086
1151
|
if (typeof setup === 'string') {
|
|
1087
|
-
return JSXElement.
|
|
1152
|
+
return JSXElement.createInstance(setup, props, key);
|
|
1088
1153
|
}
|
|
1089
|
-
return new JSXComponent(setup, props, function (context
|
|
1090
|
-
return new Component(context,
|
|
1154
|
+
return new JSXComponent(setup, props, function (context) {
|
|
1155
|
+
return new Component(context, setup, props, key);
|
|
1091
1156
|
}, key);
|
|
1092
1157
|
}
|
|
1093
1158
|
const jsxs = jsx;
|
|
1159
|
+
const JSXTextTypeOf = Symbol('JSXText');
|
|
1094
1160
|
class JSXText {
|
|
1095
1161
|
constructor(text) {
|
|
1096
1162
|
this.text = text;
|
|
1097
|
-
this.$$typeOf =
|
|
1098
|
-
}
|
|
1099
|
-
is(target) {
|
|
1100
|
-
return target.$$typeOf === this.$$typeOf;
|
|
1163
|
+
this.$$typeOf = JSXTextTypeOf;
|
|
1101
1164
|
}
|
|
1102
1165
|
}
|
|
1103
1166
|
class JSXElement {
|
|
1104
|
-
static
|
|
1105
|
-
return new JSXElement(
|
|
1167
|
+
static createInstance(type, props, key) {
|
|
1168
|
+
return new JSXElement(type, props, key);
|
|
1106
1169
|
}
|
|
1107
1170
|
constructor(type, props, key) {
|
|
1108
1171
|
this.type = type;
|
|
@@ -1110,54 +1173,17 @@ class JSXElement {
|
|
|
1110
1173
|
this.key = key;
|
|
1111
1174
|
this.$$typeOf = this.type;
|
|
1112
1175
|
}
|
|
1113
|
-
is(target) {
|
|
1114
|
-
return target.$$typeOf === this.$$typeOf;
|
|
1115
|
-
}
|
|
1116
1176
|
}
|
|
1117
1177
|
class JSXComponent {
|
|
1118
|
-
get dirty() {
|
|
1119
|
-
return this._dirty;
|
|
1120
|
-
}
|
|
1121
|
-
get changed() {
|
|
1122
|
-
return this._changed;
|
|
1123
|
-
}
|
|
1124
1178
|
constructor(type, props, factory, key) {
|
|
1125
1179
|
this.type = type;
|
|
1126
1180
|
this.props = props;
|
|
1127
1181
|
this.factory = factory;
|
|
1128
1182
|
this.key = key;
|
|
1129
1183
|
this.$$typeOf = this.type;
|
|
1130
|
-
this.parentComponent = null;
|
|
1131
|
-
this.changedSubComponents = new Set();
|
|
1132
|
-
this._dirty = true;
|
|
1133
|
-
this._changed = true;
|
|
1134
1184
|
}
|
|
1135
|
-
|
|
1136
|
-
this.
|
|
1137
|
-
this.markAsChanged();
|
|
1138
|
-
}
|
|
1139
|
-
markAsChanged(changedComponent) {
|
|
1140
|
-
if (changedComponent) {
|
|
1141
|
-
this.changedSubComponents.add(changedComponent);
|
|
1142
|
-
}
|
|
1143
|
-
if (this._changed) {
|
|
1144
|
-
return;
|
|
1145
|
-
}
|
|
1146
|
-
this._changed = true;
|
|
1147
|
-
this.parentComponent.markAsChanged(this);
|
|
1148
|
-
}
|
|
1149
|
-
reset() {
|
|
1150
|
-
this.changedSubComponents.clear();
|
|
1151
|
-
this.instance.rendered();
|
|
1152
|
-
this._dirty = this._changed = false;
|
|
1153
|
-
}
|
|
1154
|
-
is(target) {
|
|
1155
|
-
return target.$$typeOf === this.$$typeOf;
|
|
1156
|
-
}
|
|
1157
|
-
createInstance(injector) {
|
|
1158
|
-
this.parentComponent = injector.jsxNode;
|
|
1159
|
-
this.instance = this.factory(injector, this);
|
|
1160
|
-
return this.instance;
|
|
1185
|
+
createInstance(parentComponent) {
|
|
1186
|
+
return this.factory(parentComponent);
|
|
1161
1187
|
}
|
|
1162
1188
|
}
|
|
1163
1189
|
|
|
@@ -1168,37 +1194,33 @@ function withMemo(canUseMemo, render) {
|
|
|
1168
1194
|
};
|
|
1169
1195
|
}
|
|
1170
1196
|
|
|
1171
|
-
function createRenderer(
|
|
1197
|
+
function createRenderer(component, nativeRenderer) {
|
|
1172
1198
|
let isInit = true;
|
|
1173
1199
|
return function render(host) {
|
|
1174
1200
|
if (isInit) {
|
|
1175
1201
|
isInit = false;
|
|
1176
1202
|
const atom = {
|
|
1177
|
-
jsxNode:
|
|
1203
|
+
jsxNode: component,
|
|
1178
1204
|
parent: null,
|
|
1179
1205
|
sibling: null,
|
|
1180
1206
|
child: null,
|
|
1181
1207
|
nativeNode: null
|
|
1182
1208
|
};
|
|
1183
|
-
|
|
1209
|
+
componentRender(nativeRenderer, component, atom, {
|
|
1184
1210
|
isParent: true,
|
|
1185
1211
|
host
|
|
1186
1212
|
});
|
|
1187
1213
|
}
|
|
1188
1214
|
else {
|
|
1189
|
-
updateView(nativeRenderer,
|
|
1215
|
+
updateView(nativeRenderer, component);
|
|
1190
1216
|
}
|
|
1191
1217
|
};
|
|
1192
1218
|
}
|
|
1193
1219
|
function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
1194
1220
|
if (atom.jsxNode instanceof JSXComponent) {
|
|
1195
|
-
const component =
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
buildView(nativeRenderer, component, child, context);
|
|
1199
|
-
child = child.sibling;
|
|
1200
|
-
}
|
|
1201
|
-
atom.jsxNode.reset();
|
|
1221
|
+
const component = atom.jsxNode.createInstance(parentComponent);
|
|
1222
|
+
atom.jsxNode = component;
|
|
1223
|
+
componentRender(nativeRenderer, component, atom, context);
|
|
1202
1224
|
}
|
|
1203
1225
|
else {
|
|
1204
1226
|
let nativeNode;
|
|
@@ -1236,24 +1258,24 @@ function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
|
1236
1258
|
}
|
|
1237
1259
|
}
|
|
1238
1260
|
}
|
|
1239
|
-
function updateView(nativeRenderer,
|
|
1240
|
-
if (
|
|
1241
|
-
applyChanges(nativeRenderer,
|
|
1242
|
-
|
|
1261
|
+
function updateView(nativeRenderer, component) {
|
|
1262
|
+
if (component.dirty) {
|
|
1263
|
+
applyChanges(nativeRenderer, component);
|
|
1264
|
+
component.rendered();
|
|
1243
1265
|
}
|
|
1244
|
-
else if (
|
|
1245
|
-
|
|
1266
|
+
else if (component.changed) {
|
|
1267
|
+
component.changedSubComponents.forEach(child => {
|
|
1246
1268
|
updateView(nativeRenderer, child);
|
|
1247
1269
|
});
|
|
1248
|
-
|
|
1270
|
+
component.rendered();
|
|
1249
1271
|
}
|
|
1250
1272
|
}
|
|
1251
|
-
function applyChanges(nativeRenderer,
|
|
1252
|
-
const { atom, host, isParent } =
|
|
1273
|
+
function applyChanges(nativeRenderer, component) {
|
|
1274
|
+
const { atom, host, isParent } = component.$$view;
|
|
1253
1275
|
const diffAtom = atom.child;
|
|
1254
|
-
const template =
|
|
1276
|
+
const template = component.update(component.props, true);
|
|
1255
1277
|
if (template) {
|
|
1256
|
-
linkTemplate(template,
|
|
1278
|
+
linkTemplate(template, component, atom);
|
|
1257
1279
|
}
|
|
1258
1280
|
else {
|
|
1259
1281
|
atom.child = null;
|
|
@@ -1262,34 +1284,47 @@ function applyChanges(nativeRenderer, jsxComponent) {
|
|
|
1262
1284
|
host,
|
|
1263
1285
|
isParent
|
|
1264
1286
|
};
|
|
1265
|
-
diff(nativeRenderer,
|
|
1287
|
+
diff(nativeRenderer, component, atom.child, diffAtom, context, 0, 0);
|
|
1266
1288
|
const next = atom.sibling;
|
|
1267
|
-
if (next && next.jsxNode instanceof
|
|
1289
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1268
1290
|
next.jsxNode.$$view.host = context.host;
|
|
1269
1291
|
next.jsxNode.$$view.isParent = context.isParent;
|
|
1270
1292
|
}
|
|
1271
1293
|
}
|
|
1272
1294
|
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expectIndex, index) {
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1295
|
+
let prevDiffAtom = null;
|
|
1296
|
+
let firstDiffAtomIndexed = null;
|
|
1297
|
+
if (oldAtom) {
|
|
1298
|
+
prevDiffAtom = {
|
|
1276
1299
|
index,
|
|
1277
|
-
atom: oldAtom
|
|
1278
|
-
|
|
1279
|
-
|
|
1300
|
+
atom: oldAtom,
|
|
1301
|
+
prev: null
|
|
1302
|
+
};
|
|
1280
1303
|
index++;
|
|
1304
|
+
firstDiffAtomIndexed = prevDiffAtom;
|
|
1305
|
+
oldAtom = oldAtom.sibling;
|
|
1306
|
+
while (oldAtom) {
|
|
1307
|
+
const diffAtom = {
|
|
1308
|
+
index,
|
|
1309
|
+
atom: oldAtom,
|
|
1310
|
+
prev: prevDiffAtom
|
|
1311
|
+
};
|
|
1312
|
+
prevDiffAtom.next = diffAtom;
|
|
1313
|
+
prevDiffAtom = diffAtom;
|
|
1314
|
+
oldAtom = oldAtom.sibling;
|
|
1315
|
+
index++;
|
|
1316
|
+
}
|
|
1281
1317
|
}
|
|
1282
1318
|
const commits = [];
|
|
1283
1319
|
const changeCommits = {
|
|
1284
1320
|
updateComponent: (newAtom, reusedAtom, expectIndex, diffIndex) => {
|
|
1285
1321
|
commits.push((offset) => {
|
|
1286
|
-
const
|
|
1287
|
-
const instance = oldJSXComponent.instance;
|
|
1322
|
+
const instance = reusedAtom.jsxNode;
|
|
1288
1323
|
const newProps = newAtom.jsxNode.props;
|
|
1289
1324
|
const oldTemplate = instance.template;
|
|
1290
1325
|
const newTemplate = instance.update(newProps);
|
|
1291
|
-
|
|
1292
|
-
newAtom.jsxNode =
|
|
1326
|
+
instance.$$view = Object.assign({ atom: newAtom }, context);
|
|
1327
|
+
newAtom.jsxNode = instance;
|
|
1293
1328
|
if (newTemplate === oldTemplate) {
|
|
1294
1329
|
reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex !== diffIndex - offset);
|
|
1295
1330
|
return;
|
|
@@ -1307,7 +1342,7 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expect
|
|
|
1307
1342
|
atom = atom.sibling;
|
|
1308
1343
|
}
|
|
1309
1344
|
}
|
|
1310
|
-
|
|
1345
|
+
instance.rendered();
|
|
1311
1346
|
});
|
|
1312
1347
|
},
|
|
1313
1348
|
updateElement: (newAtom, oldAtom, expectIndex, oldIndex) => {
|
|
@@ -1359,23 +1394,22 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expect
|
|
|
1359
1394
|
}
|
|
1360
1395
|
};
|
|
1361
1396
|
while (newAtom) {
|
|
1362
|
-
createChanges(newAtom, expectIndex,
|
|
1397
|
+
firstDiffAtomIndexed = createChanges(newAtom, expectIndex, firstDiffAtomIndexed, changeCommits);
|
|
1363
1398
|
newAtom = newAtom.sibling;
|
|
1364
1399
|
expectIndex++;
|
|
1365
1400
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1401
|
+
let dirtyDiffAtom = firstDiffAtomIndexed;
|
|
1402
|
+
while (dirtyDiffAtom) {
|
|
1403
|
+
cleanView(nativeRenderer, dirtyDiffAtom.atom, false);
|
|
1404
|
+
dirtyDiffAtom = dirtyDiffAtom.next;
|
|
1368
1405
|
}
|
|
1369
|
-
let j = 0;
|
|
1370
1406
|
let offset = 0;
|
|
1371
|
-
const len = oldChildren.length;
|
|
1372
1407
|
for (let i = 0; i < commits.length; i++) {
|
|
1373
1408
|
const commit = commits[i];
|
|
1374
|
-
while (
|
|
1375
|
-
|
|
1376
|
-
if (current.index <= i) {
|
|
1409
|
+
while (firstDiffAtomIndexed) {
|
|
1410
|
+
if (firstDiffAtomIndexed.index <= i) {
|
|
1377
1411
|
offset++;
|
|
1378
|
-
|
|
1412
|
+
firstDiffAtomIndexed = firstDiffAtomIndexed.next;
|
|
1379
1413
|
continue;
|
|
1380
1414
|
}
|
|
1381
1415
|
break;
|
|
@@ -1393,7 +1427,7 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
|
|
|
1393
1427
|
child = child.sibling;
|
|
1394
1428
|
}
|
|
1395
1429
|
const updateContext = (atom) => {
|
|
1396
|
-
if (atom.jsxNode instanceof
|
|
1430
|
+
if (atom.jsxNode instanceof Component) {
|
|
1397
1431
|
let child = atom.child;
|
|
1398
1432
|
while (child) {
|
|
1399
1433
|
updateContext(child);
|
|
@@ -1417,17 +1451,19 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
|
|
|
1417
1451
|
updateContext(atom);
|
|
1418
1452
|
}
|
|
1419
1453
|
}
|
|
1420
|
-
function createChanges(newAtom, expectIndex,
|
|
1421
|
-
|
|
1422
|
-
|
|
1454
|
+
function createChanges(newAtom, expectIndex, diffAtomIndexed, changeCommits) {
|
|
1455
|
+
const startDiffAtom = diffAtomIndexed;
|
|
1456
|
+
while (diffAtomIndexed) {
|
|
1457
|
+
const { atom: diffAtom, index: diffIndex } = diffAtomIndexed;
|
|
1423
1458
|
const key = newAtom.jsxNode.key;
|
|
1424
1459
|
const diffKey = diffAtom.jsxNode.key;
|
|
1425
1460
|
if (key !== undefined && diffKey !== undefined) {
|
|
1426
1461
|
if (diffKey !== key) {
|
|
1462
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1427
1463
|
continue;
|
|
1428
1464
|
}
|
|
1429
1465
|
}
|
|
1430
|
-
if (newAtom.jsxNode
|
|
1466
|
+
if (newAtom.jsxNode.$$typeOf === diffAtom.jsxNode.$$typeOf) {
|
|
1431
1467
|
if (newAtom.jsxNode instanceof JSXElement) {
|
|
1432
1468
|
changeCommits.updateElement(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1433
1469
|
}
|
|
@@ -1437,11 +1473,25 @@ function createChanges(newAtom, expectIndex, oldChildren, changeCommits) {
|
|
|
1437
1473
|
else {
|
|
1438
1474
|
changeCommits.updateComponent(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1439
1475
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1476
|
+
const next = diffAtomIndexed.next;
|
|
1477
|
+
const prev = diffAtomIndexed.prev;
|
|
1478
|
+
if (!prev) {
|
|
1479
|
+
diffAtomIndexed = next;
|
|
1480
|
+
if (diffAtomIndexed) {
|
|
1481
|
+
diffAtomIndexed.prev = null;
|
|
1482
|
+
}
|
|
1483
|
+
return diffAtomIndexed;
|
|
1484
|
+
}
|
|
1485
|
+
prev.next = next;
|
|
1486
|
+
if (next) {
|
|
1487
|
+
next.prev = prev;
|
|
1488
|
+
}
|
|
1489
|
+
return startDiffAtom;
|
|
1442
1490
|
}
|
|
1491
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1443
1492
|
}
|
|
1444
1493
|
changeCommits.create(newAtom);
|
|
1494
|
+
return startDiffAtom;
|
|
1445
1495
|
}
|
|
1446
1496
|
function cleanView(nativeRenderer, atom, isClean) {
|
|
1447
1497
|
if (atom.nativeNode) {
|
|
@@ -1459,18 +1509,22 @@ function cleanView(nativeRenderer, atom, isClean) {
|
|
|
1459
1509
|
cleanView(nativeRenderer, child, isClean);
|
|
1460
1510
|
child = child.sibling;
|
|
1461
1511
|
}
|
|
1462
|
-
if (atom.jsxNode instanceof
|
|
1463
|
-
atom.jsxNode.
|
|
1512
|
+
if (atom.jsxNode instanceof Component) {
|
|
1513
|
+
atom.jsxNode.destroy();
|
|
1464
1514
|
}
|
|
1465
1515
|
}
|
|
1466
|
-
function componentRender(
|
|
1467
|
-
const component = jsxComponent.createInstance(parentComponent);
|
|
1516
|
+
function componentRender(nativeRenderer, component, from, context) {
|
|
1468
1517
|
const template = component.render();
|
|
1469
1518
|
if (template) {
|
|
1470
|
-
linkTemplate(template,
|
|
1519
|
+
linkTemplate(template, component, from);
|
|
1471
1520
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1521
|
+
component.$$view = Object.assign({ atom: from }, context);
|
|
1522
|
+
let child = from.child;
|
|
1523
|
+
while (child) {
|
|
1524
|
+
buildView(nativeRenderer, component, child, context);
|
|
1525
|
+
child = child.sibling;
|
|
1526
|
+
}
|
|
1527
|
+
component.rendered();
|
|
1474
1528
|
}
|
|
1475
1529
|
function createChainByComponentFactory(jsxComponent, parent) {
|
|
1476
1530
|
return {
|
|
@@ -1481,7 +1535,7 @@ function createChainByComponentFactory(jsxComponent, parent) {
|
|
|
1481
1535
|
nativeNode: null
|
|
1482
1536
|
};
|
|
1483
1537
|
}
|
|
1484
|
-
function createChainByJSXElement(
|
|
1538
|
+
function createChainByJSXElement(component, element, parent) {
|
|
1485
1539
|
const atom = {
|
|
1486
1540
|
jsxNode: element,
|
|
1487
1541
|
parent,
|
|
@@ -1491,7 +1545,7 @@ function createChainByJSXElement(jsxComponent, element, parent) {
|
|
|
1491
1545
|
};
|
|
1492
1546
|
if (Reflect.has(element.props, 'children')) {
|
|
1493
1547
|
const jsxChildren = element.props.children;
|
|
1494
|
-
const children = createChainByChildren(
|
|
1548
|
+
const children = createChainByChildren(component, Array.isArray(jsxChildren) ? jsxChildren : [jsxChildren], atom, []);
|
|
1495
1549
|
link(atom, children);
|
|
1496
1550
|
}
|
|
1497
1551
|
return atom;
|
|
@@ -1505,34 +1559,34 @@ function createChainByJSXText(node, parent) {
|
|
|
1505
1559
|
nativeNode: null
|
|
1506
1560
|
};
|
|
1507
1561
|
}
|
|
1508
|
-
function createChainByChildren(
|
|
1562
|
+
function createChainByChildren(component, children, parent, atoms) {
|
|
1509
1563
|
for (const item of children) {
|
|
1510
|
-
if (item instanceof JSXElement) {
|
|
1511
|
-
atoms.push(createChainByJSXElement(jsxComponent, item, parent));
|
|
1512
|
-
continue;
|
|
1513
|
-
}
|
|
1514
|
-
if (item instanceof JSXComponent) {
|
|
1515
|
-
const childAtom = createChainByComponentFactory(item, parent);
|
|
1516
|
-
atoms.push(childAtom);
|
|
1517
|
-
continue;
|
|
1518
|
-
}
|
|
1519
|
-
if (typeof item === 'string' && item.length) {
|
|
1520
|
-
atoms.push(createChainByJSXText(new JSXText(item), parent));
|
|
1521
|
-
continue;
|
|
1522
|
-
}
|
|
1523
|
-
if (Array.isArray(item)) {
|
|
1524
|
-
createChainByChildren(jsxComponent, item, parent, atoms);
|
|
1525
|
-
continue;
|
|
1526
|
-
}
|
|
1527
1564
|
if (item !== null && typeof item !== 'undefined') {
|
|
1565
|
+
if (item instanceof JSXElement) {
|
|
1566
|
+
atoms.push(createChainByJSXElement(component, item, parent));
|
|
1567
|
+
continue;
|
|
1568
|
+
}
|
|
1569
|
+
if (item instanceof JSXComponent) {
|
|
1570
|
+
const childAtom = createChainByComponentFactory(item, parent);
|
|
1571
|
+
atoms.push(childAtom);
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
if (typeof item === 'string' && item.length) {
|
|
1575
|
+
atoms.push(createChainByJSXText(new JSXText(item), parent));
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (Array.isArray(item)) {
|
|
1579
|
+
createChainByChildren(component, item, parent, atoms);
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1528
1582
|
atoms.push(createChainByJSXText(new JSXText(String(item)), parent));
|
|
1529
1583
|
}
|
|
1530
1584
|
}
|
|
1531
1585
|
return atoms;
|
|
1532
1586
|
}
|
|
1533
|
-
function linkTemplate(template,
|
|
1587
|
+
function linkTemplate(template, component, parent) {
|
|
1534
1588
|
const children = Array.isArray(template) ? template : [template];
|
|
1535
|
-
const newChildren = createChainByChildren(
|
|
1589
|
+
const newChildren = createChainByChildren(component, children, parent, []);
|
|
1536
1590
|
link(parent, newChildren);
|
|
1537
1591
|
}
|
|
1538
1592
|
function link(parent, children) {
|
|
@@ -1716,11 +1770,9 @@ function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn) {
|
|
|
1716
1770
|
/**
|
|
1717
1771
|
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
1718
1772
|
*/
|
|
1719
|
-
class RootComponent extends
|
|
1720
|
-
constructor(
|
|
1721
|
-
super(factory, {}
|
|
1722
|
-
return new Component(parentComponent, jsxNode, {});
|
|
1723
|
-
});
|
|
1773
|
+
class RootComponent extends Component {
|
|
1774
|
+
constructor(parentInjector, factory) {
|
|
1775
|
+
super(parentInjector, factory, {});
|
|
1724
1776
|
this.onChange = null;
|
|
1725
1777
|
}
|
|
1726
1778
|
markAsChanged(changedComponent) {
|
|
@@ -1737,13 +1789,13 @@ const viewflyErrorFn = makeError('Viewfly');
|
|
|
1737
1789
|
function viewfly({ context, nativeRenderer, autoUpdate, root }) {
|
|
1738
1790
|
const appProviders = [];
|
|
1739
1791
|
let destroyed = false;
|
|
1740
|
-
const rootComponent = new RootComponent(() => {
|
|
1792
|
+
const rootComponent = new RootComponent(context || null, () => {
|
|
1741
1793
|
provide(appProviders);
|
|
1742
1794
|
return () => {
|
|
1743
1795
|
return destroyed ? null : root;
|
|
1744
1796
|
};
|
|
1745
|
-
}
|
|
1746
|
-
const render = createRenderer(rootComponent, nativeRenderer
|
|
1797
|
+
});
|
|
1798
|
+
const render = createRenderer(rootComponent, nativeRenderer);
|
|
1747
1799
|
let isStarted = false;
|
|
1748
1800
|
let task = null;
|
|
1749
1801
|
function microTask(callback) {
|