@viewfly/core 0.0.29 → 0.0.31
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 +14 -28
- package/bundles/foundation/renderer.d.ts +1 -2
- package/bundles/foundation/root.component.d.ts +5 -4
- package/bundles/index.esm.js +224 -169
- package/bundles/index.js +224 -169
- 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
|
|
1090
|
-
return new Component(context,
|
|
1154
|
+
return JSXComponent.createInstance(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,16 +1173,10 @@ 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
|
-
|
|
1119
|
-
return
|
|
1120
|
-
}
|
|
1121
|
-
get changed() {
|
|
1122
|
-
return this._changed;
|
|
1178
|
+
static createInstance(type, props, factory, key) {
|
|
1179
|
+
return new JSXComponent(type, props, factory, key);
|
|
1123
1180
|
}
|
|
1124
1181
|
constructor(type, props, factory, key) {
|
|
1125
1182
|
this.type = type;
|
|
@@ -1127,37 +1184,9 @@ class JSXComponent {
|
|
|
1127
1184
|
this.factory = factory;
|
|
1128
1185
|
this.key = key;
|
|
1129
1186
|
this.$$typeOf = this.type;
|
|
1130
|
-
this.parentComponent = null;
|
|
1131
|
-
this.changedSubComponents = new Set();
|
|
1132
|
-
this._dirty = true;
|
|
1133
|
-
this._changed = true;
|
|
1134
1187
|
}
|
|
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;
|
|
1188
|
+
createInstance(parentComponent) {
|
|
1189
|
+
return this.factory(parentComponent);
|
|
1161
1190
|
}
|
|
1162
1191
|
}
|
|
1163
1192
|
|
|
@@ -1168,37 +1197,33 @@ function withMemo(canUseMemo, render) {
|
|
|
1168
1197
|
};
|
|
1169
1198
|
}
|
|
1170
1199
|
|
|
1171
|
-
function createRenderer(
|
|
1200
|
+
function createRenderer(component, nativeRenderer) {
|
|
1172
1201
|
let isInit = true;
|
|
1173
1202
|
return function render(host) {
|
|
1174
1203
|
if (isInit) {
|
|
1175
1204
|
isInit = false;
|
|
1176
1205
|
const atom = {
|
|
1177
|
-
jsxNode:
|
|
1206
|
+
jsxNode: component,
|
|
1178
1207
|
parent: null,
|
|
1179
1208
|
sibling: null,
|
|
1180
1209
|
child: null,
|
|
1181
1210
|
nativeNode: null
|
|
1182
1211
|
};
|
|
1183
|
-
|
|
1212
|
+
componentRender(nativeRenderer, component, atom, {
|
|
1184
1213
|
isParent: true,
|
|
1185
1214
|
host
|
|
1186
1215
|
});
|
|
1187
1216
|
}
|
|
1188
1217
|
else {
|
|
1189
|
-
updateView(nativeRenderer,
|
|
1218
|
+
updateView(nativeRenderer, component);
|
|
1190
1219
|
}
|
|
1191
1220
|
};
|
|
1192
1221
|
}
|
|
1193
1222
|
function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
1194
1223
|
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();
|
|
1224
|
+
const component = atom.jsxNode.createInstance(parentComponent);
|
|
1225
|
+
atom.jsxNode = component;
|
|
1226
|
+
componentRender(nativeRenderer, component, atom, context);
|
|
1202
1227
|
}
|
|
1203
1228
|
else {
|
|
1204
1229
|
let nativeNode;
|
|
@@ -1236,24 +1261,24 @@ function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
|
1236
1261
|
}
|
|
1237
1262
|
}
|
|
1238
1263
|
}
|
|
1239
|
-
function updateView(nativeRenderer,
|
|
1240
|
-
if (
|
|
1241
|
-
applyChanges(nativeRenderer,
|
|
1242
|
-
|
|
1264
|
+
function updateView(nativeRenderer, component) {
|
|
1265
|
+
if (component.dirty) {
|
|
1266
|
+
applyChanges(nativeRenderer, component);
|
|
1267
|
+
component.rendered();
|
|
1243
1268
|
}
|
|
1244
|
-
else if (
|
|
1245
|
-
|
|
1269
|
+
else if (component.changed) {
|
|
1270
|
+
component.changedSubComponents.forEach(child => {
|
|
1246
1271
|
updateView(nativeRenderer, child);
|
|
1247
1272
|
});
|
|
1248
|
-
|
|
1273
|
+
component.rendered();
|
|
1249
1274
|
}
|
|
1250
1275
|
}
|
|
1251
|
-
function applyChanges(nativeRenderer,
|
|
1252
|
-
const { atom, host, isParent } =
|
|
1276
|
+
function applyChanges(nativeRenderer, component) {
|
|
1277
|
+
const { atom, host, isParent } = component.$$view;
|
|
1253
1278
|
const diffAtom = atom.child;
|
|
1254
|
-
const template =
|
|
1279
|
+
const template = component.update(component.props, true);
|
|
1255
1280
|
if (template) {
|
|
1256
|
-
linkTemplate(template,
|
|
1281
|
+
linkTemplate(template, component, atom);
|
|
1257
1282
|
}
|
|
1258
1283
|
else {
|
|
1259
1284
|
atom.child = null;
|
|
@@ -1262,34 +1287,47 @@ function applyChanges(nativeRenderer, jsxComponent) {
|
|
|
1262
1287
|
host,
|
|
1263
1288
|
isParent
|
|
1264
1289
|
};
|
|
1265
|
-
diff(nativeRenderer,
|
|
1290
|
+
diff(nativeRenderer, component, atom.child, diffAtom, context, 0, 0);
|
|
1266
1291
|
const next = atom.sibling;
|
|
1267
|
-
if (next && next.jsxNode instanceof
|
|
1292
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1268
1293
|
next.jsxNode.$$view.host = context.host;
|
|
1269
1294
|
next.jsxNode.$$view.isParent = context.isParent;
|
|
1270
1295
|
}
|
|
1271
1296
|
}
|
|
1272
1297
|
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expectIndex, index) {
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1298
|
+
let prevDiffAtom = null;
|
|
1299
|
+
let firstDiffAtomIndexed = null;
|
|
1300
|
+
if (oldAtom) {
|
|
1301
|
+
prevDiffAtom = {
|
|
1276
1302
|
index,
|
|
1277
|
-
atom: oldAtom
|
|
1278
|
-
|
|
1279
|
-
|
|
1303
|
+
atom: oldAtom,
|
|
1304
|
+
prev: null
|
|
1305
|
+
};
|
|
1280
1306
|
index++;
|
|
1307
|
+
firstDiffAtomIndexed = prevDiffAtom;
|
|
1308
|
+
oldAtom = oldAtom.sibling;
|
|
1309
|
+
while (oldAtom) {
|
|
1310
|
+
const diffAtom = {
|
|
1311
|
+
index,
|
|
1312
|
+
atom: oldAtom,
|
|
1313
|
+
prev: prevDiffAtom
|
|
1314
|
+
};
|
|
1315
|
+
prevDiffAtom.next = diffAtom;
|
|
1316
|
+
prevDiffAtom = diffAtom;
|
|
1317
|
+
oldAtom = oldAtom.sibling;
|
|
1318
|
+
index++;
|
|
1319
|
+
}
|
|
1281
1320
|
}
|
|
1282
1321
|
const commits = [];
|
|
1283
1322
|
const changeCommits = {
|
|
1284
1323
|
updateComponent: (newAtom, reusedAtom, expectIndex, diffIndex) => {
|
|
1285
1324
|
commits.push((offset) => {
|
|
1286
|
-
const
|
|
1287
|
-
const instance = oldJSXComponent.instance;
|
|
1325
|
+
const instance = reusedAtom.jsxNode;
|
|
1288
1326
|
const newProps = newAtom.jsxNode.props;
|
|
1289
1327
|
const oldTemplate = instance.template;
|
|
1290
1328
|
const newTemplate = instance.update(newProps);
|
|
1291
|
-
|
|
1292
|
-
newAtom.jsxNode =
|
|
1329
|
+
instance.$$view = Object.assign({ atom: newAtom }, context);
|
|
1330
|
+
newAtom.jsxNode = instance;
|
|
1293
1331
|
if (newTemplate === oldTemplate) {
|
|
1294
1332
|
reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex !== diffIndex - offset);
|
|
1295
1333
|
return;
|
|
@@ -1307,7 +1345,7 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expect
|
|
|
1307
1345
|
atom = atom.sibling;
|
|
1308
1346
|
}
|
|
1309
1347
|
}
|
|
1310
|
-
|
|
1348
|
+
instance.rendered();
|
|
1311
1349
|
});
|
|
1312
1350
|
},
|
|
1313
1351
|
updateElement: (newAtom, oldAtom, expectIndex, oldIndex) => {
|
|
@@ -1359,23 +1397,22 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expect
|
|
|
1359
1397
|
}
|
|
1360
1398
|
};
|
|
1361
1399
|
while (newAtom) {
|
|
1362
|
-
createChanges(newAtom, expectIndex,
|
|
1400
|
+
firstDiffAtomIndexed = createChanges(newAtom, expectIndex, firstDiffAtomIndexed, changeCommits);
|
|
1363
1401
|
newAtom = newAtom.sibling;
|
|
1364
1402
|
expectIndex++;
|
|
1365
1403
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1404
|
+
let dirtyDiffAtom = firstDiffAtomIndexed;
|
|
1405
|
+
while (dirtyDiffAtom) {
|
|
1406
|
+
cleanView(nativeRenderer, dirtyDiffAtom.atom, false);
|
|
1407
|
+
dirtyDiffAtom = dirtyDiffAtom.next;
|
|
1368
1408
|
}
|
|
1369
|
-
let j = 0;
|
|
1370
1409
|
let offset = 0;
|
|
1371
|
-
const len = oldChildren.length;
|
|
1372
1410
|
for (let i = 0; i < commits.length; i++) {
|
|
1373
1411
|
const commit = commits[i];
|
|
1374
|
-
while (
|
|
1375
|
-
|
|
1376
|
-
if (current.index <= i) {
|
|
1412
|
+
while (firstDiffAtomIndexed) {
|
|
1413
|
+
if (firstDiffAtomIndexed.index <= i) {
|
|
1377
1414
|
offset++;
|
|
1378
|
-
|
|
1415
|
+
firstDiffAtomIndexed = firstDiffAtomIndexed.next;
|
|
1379
1416
|
continue;
|
|
1380
1417
|
}
|
|
1381
1418
|
break;
|
|
@@ -1393,7 +1430,7 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
|
|
|
1393
1430
|
child = child.sibling;
|
|
1394
1431
|
}
|
|
1395
1432
|
const updateContext = (atom) => {
|
|
1396
|
-
if (atom.jsxNode instanceof
|
|
1433
|
+
if (atom.jsxNode instanceof Component) {
|
|
1397
1434
|
let child = atom.child;
|
|
1398
1435
|
while (child) {
|
|
1399
1436
|
updateContext(child);
|
|
@@ -1417,17 +1454,19 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
|
|
|
1417
1454
|
updateContext(atom);
|
|
1418
1455
|
}
|
|
1419
1456
|
}
|
|
1420
|
-
function createChanges(newAtom, expectIndex,
|
|
1421
|
-
|
|
1422
|
-
|
|
1457
|
+
function createChanges(newAtom, expectIndex, diffAtomIndexed, changeCommits) {
|
|
1458
|
+
const startDiffAtom = diffAtomIndexed;
|
|
1459
|
+
while (diffAtomIndexed) {
|
|
1460
|
+
const { atom: diffAtom, index: diffIndex } = diffAtomIndexed;
|
|
1423
1461
|
const key = newAtom.jsxNode.key;
|
|
1424
1462
|
const diffKey = diffAtom.jsxNode.key;
|
|
1425
1463
|
if (key !== undefined && diffKey !== undefined) {
|
|
1426
1464
|
if (diffKey !== key) {
|
|
1465
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1427
1466
|
continue;
|
|
1428
1467
|
}
|
|
1429
1468
|
}
|
|
1430
|
-
if (newAtom.jsxNode
|
|
1469
|
+
if (newAtom.jsxNode.$$typeOf === diffAtom.jsxNode.$$typeOf) {
|
|
1431
1470
|
if (newAtom.jsxNode instanceof JSXElement) {
|
|
1432
1471
|
changeCommits.updateElement(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1433
1472
|
}
|
|
@@ -1437,11 +1476,25 @@ function createChanges(newAtom, expectIndex, oldChildren, changeCommits) {
|
|
|
1437
1476
|
else {
|
|
1438
1477
|
changeCommits.updateComponent(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1439
1478
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1479
|
+
const next = diffAtomIndexed.next;
|
|
1480
|
+
const prev = diffAtomIndexed.prev;
|
|
1481
|
+
if (!prev) {
|
|
1482
|
+
diffAtomIndexed = next;
|
|
1483
|
+
if (diffAtomIndexed) {
|
|
1484
|
+
diffAtomIndexed.prev = null;
|
|
1485
|
+
}
|
|
1486
|
+
return diffAtomIndexed;
|
|
1487
|
+
}
|
|
1488
|
+
prev.next = next;
|
|
1489
|
+
if (next) {
|
|
1490
|
+
next.prev = prev;
|
|
1491
|
+
}
|
|
1492
|
+
return startDiffAtom;
|
|
1442
1493
|
}
|
|
1494
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1443
1495
|
}
|
|
1444
1496
|
changeCommits.create(newAtom);
|
|
1497
|
+
return startDiffAtom;
|
|
1445
1498
|
}
|
|
1446
1499
|
function cleanView(nativeRenderer, atom, isClean) {
|
|
1447
1500
|
if (atom.nativeNode) {
|
|
@@ -1459,18 +1512,22 @@ function cleanView(nativeRenderer, atom, isClean) {
|
|
|
1459
1512
|
cleanView(nativeRenderer, child, isClean);
|
|
1460
1513
|
child = child.sibling;
|
|
1461
1514
|
}
|
|
1462
|
-
if (atom.jsxNode instanceof
|
|
1463
|
-
atom.jsxNode.
|
|
1515
|
+
if (atom.jsxNode instanceof Component) {
|
|
1516
|
+
atom.jsxNode.destroy();
|
|
1464
1517
|
}
|
|
1465
1518
|
}
|
|
1466
|
-
function componentRender(
|
|
1467
|
-
const component = jsxComponent.createInstance(parentComponent);
|
|
1519
|
+
function componentRender(nativeRenderer, component, from, context) {
|
|
1468
1520
|
const template = component.render();
|
|
1469
1521
|
if (template) {
|
|
1470
|
-
linkTemplate(template,
|
|
1522
|
+
linkTemplate(template, component, from);
|
|
1471
1523
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1524
|
+
component.$$view = Object.assign({ atom: from }, context);
|
|
1525
|
+
let child = from.child;
|
|
1526
|
+
while (child) {
|
|
1527
|
+
buildView(nativeRenderer, component, child, context);
|
|
1528
|
+
child = child.sibling;
|
|
1529
|
+
}
|
|
1530
|
+
component.rendered();
|
|
1474
1531
|
}
|
|
1475
1532
|
function createChainByComponentFactory(jsxComponent, parent) {
|
|
1476
1533
|
return {
|
|
@@ -1481,7 +1538,7 @@ function createChainByComponentFactory(jsxComponent, parent) {
|
|
|
1481
1538
|
nativeNode: null
|
|
1482
1539
|
};
|
|
1483
1540
|
}
|
|
1484
|
-
function createChainByJSXElement(
|
|
1541
|
+
function createChainByJSXElement(component, element, parent) {
|
|
1485
1542
|
const atom = {
|
|
1486
1543
|
jsxNode: element,
|
|
1487
1544
|
parent,
|
|
@@ -1491,7 +1548,7 @@ function createChainByJSXElement(jsxComponent, element, parent) {
|
|
|
1491
1548
|
};
|
|
1492
1549
|
if (Reflect.has(element.props, 'children')) {
|
|
1493
1550
|
const jsxChildren = element.props.children;
|
|
1494
|
-
const children = createChainByChildren(
|
|
1551
|
+
const children = createChainByChildren(component, Array.isArray(jsxChildren) ? jsxChildren : [jsxChildren], atom, []);
|
|
1495
1552
|
link(atom, children);
|
|
1496
1553
|
}
|
|
1497
1554
|
return atom;
|
|
@@ -1505,34 +1562,34 @@ function createChainByJSXText(node, parent) {
|
|
|
1505
1562
|
nativeNode: null
|
|
1506
1563
|
};
|
|
1507
1564
|
}
|
|
1508
|
-
function createChainByChildren(
|
|
1565
|
+
function createChainByChildren(component, children, parent, atoms) {
|
|
1509
1566
|
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
1567
|
if (item !== null && typeof item !== 'undefined') {
|
|
1568
|
+
if (item instanceof JSXElement) {
|
|
1569
|
+
atoms.push(createChainByJSXElement(component, item, parent));
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
if (item instanceof JSXComponent) {
|
|
1573
|
+
const childAtom = createChainByComponentFactory(item, parent);
|
|
1574
|
+
atoms.push(childAtom);
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
if (typeof item === 'string' && item.length) {
|
|
1578
|
+
atoms.push(createChainByJSXText(new JSXText(item), parent));
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
if (Array.isArray(item)) {
|
|
1582
|
+
createChainByChildren(component, item, parent, atoms);
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1528
1585
|
atoms.push(createChainByJSXText(new JSXText(String(item)), parent));
|
|
1529
1586
|
}
|
|
1530
1587
|
}
|
|
1531
1588
|
return atoms;
|
|
1532
1589
|
}
|
|
1533
|
-
function linkTemplate(template,
|
|
1590
|
+
function linkTemplate(template, component, parent) {
|
|
1534
1591
|
const children = Array.isArray(template) ? template : [template];
|
|
1535
|
-
const newChildren = createChainByChildren(
|
|
1592
|
+
const newChildren = createChainByChildren(component, children, parent, []);
|
|
1536
1593
|
link(parent, newChildren);
|
|
1537
1594
|
}
|
|
1538
1595
|
function link(parent, children) {
|
|
@@ -1716,11 +1773,9 @@ function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn) {
|
|
|
1716
1773
|
/**
|
|
1717
1774
|
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
1718
1775
|
*/
|
|
1719
|
-
class RootComponent extends
|
|
1720
|
-
constructor(
|
|
1721
|
-
super(factory, {}
|
|
1722
|
-
return new Component(parentComponent, jsxNode, {});
|
|
1723
|
-
});
|
|
1776
|
+
class RootComponent extends Component {
|
|
1777
|
+
constructor(parentInjector, factory) {
|
|
1778
|
+
super(parentInjector, factory, {});
|
|
1724
1779
|
this.onChange = null;
|
|
1725
1780
|
}
|
|
1726
1781
|
markAsChanged(changedComponent) {
|
|
@@ -1737,13 +1792,13 @@ const viewflyErrorFn = makeError('Viewfly');
|
|
|
1737
1792
|
function viewfly({ context, nativeRenderer, autoUpdate, root }) {
|
|
1738
1793
|
const appProviders = [];
|
|
1739
1794
|
let destroyed = false;
|
|
1740
|
-
const rootComponent = new RootComponent(() => {
|
|
1795
|
+
const rootComponent = new RootComponent(context || null, () => {
|
|
1741
1796
|
provide(appProviders);
|
|
1742
1797
|
return () => {
|
|
1743
1798
|
return destroyed ? null : root;
|
|
1744
1799
|
};
|
|
1745
|
-
}
|
|
1746
|
-
const render = createRenderer(rootComponent, nativeRenderer
|
|
1800
|
+
});
|
|
1801
|
+
const render = createRenderer(rootComponent, nativeRenderer);
|
|
1747
1802
|
let isStarted = false;
|
|
1748
1803
|
let task = null;
|
|
1749
1804
|
function microTask(callback) {
|