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