@viewfly/core 0.0.28 → 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/_api.d.ts +2 -2
- package/bundles/foundation/_utils.d.ts +8 -6
- package/bundles/foundation/component.d.ts +10 -16
- package/bundles/foundation/jsx-element.d.ts +16 -10
- package/bundles/foundation/memo.d.ts +1 -1
- package/bundles/foundation/root.component.d.ts +1 -1
- package/bundles/foundation/types.d.ts +1 -1
- package/bundles/index.esm.js +270 -211
- package/bundles/index.js +270 -211
- 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 '';
|
|
@@ -626,15 +643,6 @@ function getSetupContext(need = true) {
|
|
|
626
643
|
function getSignalDepsContext() {
|
|
627
644
|
return signalDepsStack[signalDepsStack.length - 1];
|
|
628
645
|
}
|
|
629
|
-
class JSXComponent {
|
|
630
|
-
constructor(props, factory) {
|
|
631
|
-
this.props = props;
|
|
632
|
-
this.factory = factory;
|
|
633
|
-
}
|
|
634
|
-
createInstance(injector) {
|
|
635
|
-
return this.factory(injector, this.props);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
646
|
/**
|
|
639
647
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
640
648
|
*/
|
|
@@ -645,11 +653,12 @@ class Component extends ReflectiveInjector {
|
|
|
645
653
|
get changed() {
|
|
646
654
|
return this._changed;
|
|
647
655
|
}
|
|
648
|
-
constructor(
|
|
649
|
-
super(
|
|
656
|
+
constructor(parentComponent, type, props, key) {
|
|
657
|
+
super(parentComponent, [{
|
|
650
658
|
provide: Injector,
|
|
651
659
|
useFactory: () => this
|
|
652
660
|
}]);
|
|
661
|
+
this.parentComponent = parentComponent;
|
|
653
662
|
this.type = type;
|
|
654
663
|
this.props = props;
|
|
655
664
|
this.key = key;
|
|
@@ -664,22 +673,29 @@ class Component extends ReflectiveInjector {
|
|
|
664
673
|
this.updatedDestroyCallbacks = [];
|
|
665
674
|
this.propsChangedDestroyCallbacks = [];
|
|
666
675
|
this.isFirstRending = true;
|
|
667
|
-
this.parentComponent = this.parentInjector;
|
|
668
676
|
}
|
|
669
|
-
|
|
670
|
-
|
|
677
|
+
markAsDirtied() {
|
|
678
|
+
this._dirty = true;
|
|
679
|
+
this.markAsChanged();
|
|
671
680
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
+
}
|
|
675
692
|
}
|
|
676
|
-
|
|
693
|
+
render() {
|
|
677
694
|
const self = this;
|
|
678
|
-
const
|
|
695
|
+
const proxiesProps = new Proxy(this.props, {
|
|
679
696
|
get(_, key) {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
}
|
|
697
|
+
// 必须用 self,因为 props 会随着页面更新变更,使用 self 才能更新引用
|
|
698
|
+
return self.props[key];
|
|
683
699
|
},
|
|
684
700
|
set() {
|
|
685
701
|
// 防止因外部捕获异常引引起的缓存未清理的问题
|
|
@@ -691,78 +707,66 @@ class Component extends ReflectiveInjector {
|
|
|
691
707
|
});
|
|
692
708
|
componentSetupStack.push(this);
|
|
693
709
|
let isSetup = true;
|
|
694
|
-
const render = this.type(
|
|
710
|
+
const render = this.type(proxiesProps);
|
|
695
711
|
const isRenderFn = typeof render === 'function';
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
for (const ref of refs) {
|
|
700
|
-
ref.bind(
|
|
712
|
+
this.instance = isRenderFn ? { $render: render } : render;
|
|
713
|
+
this.refs = toRefs(this.props.ref);
|
|
714
|
+
this.mountCallbacks.push(() => {
|
|
715
|
+
for (const ref of this.refs) {
|
|
716
|
+
ref.bind(this.instance);
|
|
701
717
|
}
|
|
702
718
|
});
|
|
703
|
-
|
|
704
|
-
for (const ref of refs) {
|
|
705
|
-
ref.unBind(
|
|
719
|
+
this.destroyCallbacks.push(() => {
|
|
720
|
+
for (const ref of this.refs) {
|
|
721
|
+
ref.unBind(this.instance);
|
|
706
722
|
}
|
|
707
723
|
});
|
|
708
724
|
isSetup = false;
|
|
709
725
|
componentSetupStack.pop();
|
|
710
726
|
signalDepsStack.push([]);
|
|
711
|
-
let template =
|
|
727
|
+
let template = this.instance.$render();
|
|
712
728
|
const deps = signalDepsStack.pop();
|
|
713
|
-
this.unWatch = useEffect(deps, () => {
|
|
729
|
+
this.unWatch = useEffect(Array.from(new Set(deps)), () => {
|
|
714
730
|
this.markAsDirtied();
|
|
715
731
|
});
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
render: (newProps, oldProps) => {
|
|
719
|
-
if (newProps !== oldProps) {
|
|
720
|
-
const { add, remove, replace } = getObjectChanges(newProps, oldProps);
|
|
721
|
-
if (add.length || remove.length || replace.length) {
|
|
722
|
-
this.invokePropsChangedHooks(newProps);
|
|
723
|
-
}
|
|
724
|
-
const newRefs = toRefs(newProps.ref);
|
|
725
|
-
for (const oldRef of refs) {
|
|
726
|
-
if (!newRefs.includes(oldRef)) {
|
|
727
|
-
oldRef.unBind(componentInstance);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
for (const newRef of newRefs) {
|
|
731
|
-
if (!refs.includes(newRef)) {
|
|
732
|
-
newRef.bind(componentInstance);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
refs = newRefs;
|
|
736
|
-
}
|
|
737
|
-
if (typeof componentInstance.$shouldUpdate === 'function') {
|
|
738
|
-
if (!componentInstance.$shouldUpdate(newProps, oldProps)) {
|
|
739
|
-
return template;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
this.unWatch();
|
|
743
|
-
signalDepsStack.push([]);
|
|
744
|
-
template = componentInstance.$render();
|
|
745
|
-
const deps = signalDepsStack.pop();
|
|
746
|
-
this.unWatch = useEffect(deps, () => {
|
|
747
|
-
this.markAsDirtied();
|
|
748
|
-
});
|
|
749
|
-
return template;
|
|
750
|
-
}
|
|
751
|
-
};
|
|
732
|
+
this.template = template;
|
|
733
|
+
return template;
|
|
752
734
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
this.
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
735
|
+
update(newProps, forceUpdate = false) {
|
|
736
|
+
const oldProps = this.props;
|
|
737
|
+
const { add, remove, replace } = getObjectChanges(newProps, this.props);
|
|
738
|
+
if (add.length || remove.length || replace.length) {
|
|
739
|
+
this.invokePropsChangedHooks(newProps);
|
|
740
|
+
}
|
|
741
|
+
const newRefs = toRefs(newProps.ref);
|
|
742
|
+
for (const oldRef of this.refs) {
|
|
743
|
+
if (!newRefs.includes(oldRef)) {
|
|
744
|
+
oldRef.unBind(this.instance);
|
|
745
|
+
}
|
|
760
746
|
}
|
|
761
|
-
|
|
762
|
-
|
|
747
|
+
for (const newRef of newRefs) {
|
|
748
|
+
if (!this.refs.includes(newRef)) {
|
|
749
|
+
newRef.bind(this.instance);
|
|
750
|
+
}
|
|
763
751
|
}
|
|
764
|
-
this.
|
|
765
|
-
this.
|
|
752
|
+
this.refs = newRefs;
|
|
753
|
+
if (!forceUpdate && typeof this.instance.$useMemo === 'function') {
|
|
754
|
+
if (this.instance.$useMemo(newProps, oldProps)) {
|
|
755
|
+
return this.template;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
this.unWatch();
|
|
759
|
+
signalDepsStack.push([]);
|
|
760
|
+
this.template = this.instance.$render();
|
|
761
|
+
const deps = signalDepsStack.pop();
|
|
762
|
+
this.unWatch = useEffect(Array.from(new Set(deps)), () => {
|
|
763
|
+
this.markAsDirtied();
|
|
764
|
+
});
|
|
765
|
+
return this.template;
|
|
766
|
+
}
|
|
767
|
+
provide(providers) {
|
|
768
|
+
providers = Array.isArray(providers) ? providers : [providers];
|
|
769
|
+
this.normalizedProviders.unshift(...providers.map(i => normalizeProvider(i)));
|
|
766
770
|
}
|
|
767
771
|
rendered() {
|
|
768
772
|
this.changedSubComponents.clear();
|
|
@@ -1016,10 +1020,48 @@ function invokeDepFn(fn) {
|
|
|
1016
1020
|
const data = fn();
|
|
1017
1021
|
signalDepsStack.pop();
|
|
1018
1022
|
return {
|
|
1019
|
-
deps,
|
|
1023
|
+
deps: Array.from(new Set(deps)),
|
|
1020
1024
|
data
|
|
1021
1025
|
};
|
|
1022
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
|
+
}
|
|
1023
1065
|
/**
|
|
1024
1066
|
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1025
1067
|
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
@@ -1031,29 +1073,10 @@ function useDerived(callback, isContinue) {
|
|
|
1031
1073
|
let { data, deps } = invokeDepFn(callback);
|
|
1032
1074
|
const signal = useSignal(data);
|
|
1033
1075
|
const component = getSetupContext(false);
|
|
1034
|
-
const
|
|
1035
|
-
function listen(model, deps, callback, unListenRef, isContinue) {
|
|
1036
|
-
const nextListen = () => {
|
|
1037
|
-
unListenRef.unListen();
|
|
1038
|
-
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
1039
|
-
model.set(nextData);
|
|
1040
|
-
if (typeof isContinue !== 'function' || isContinue(nextData) !== false) {
|
|
1041
|
-
listen(model, nextDeps, callback, unListenRef, isContinue);
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1044
|
-
unListenRef.unListen = () => {
|
|
1045
|
-
for (const s of deps) {
|
|
1046
|
-
s[depsKey].delete(nextListen);
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
for (const s of deps) {
|
|
1050
|
-
s[depsKey].add(nextListen);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
listen(signal, deps, callback, unListenRef, isContinue);
|
|
1076
|
+
const unListen = listen(signal, deps, callback, isContinue);
|
|
1054
1077
|
if (component) {
|
|
1055
1078
|
component.destroyCallbacks.push(() => {
|
|
1056
|
-
|
|
1079
|
+
unListen();
|
|
1057
1080
|
});
|
|
1058
1081
|
}
|
|
1059
1082
|
return signal;
|
|
@@ -1116,6 +1139,9 @@ function inject(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.S
|
|
|
1116
1139
|
return component.get(token, notFoundValue, flags);
|
|
1117
1140
|
}
|
|
1118
1141
|
|
|
1142
|
+
class NativeRenderer {
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1119
1145
|
function Fragment(props) {
|
|
1120
1146
|
return () => {
|
|
1121
1147
|
return props.children;
|
|
@@ -1123,25 +1149,23 @@ function Fragment(props) {
|
|
|
1123
1149
|
}
|
|
1124
1150
|
function jsx(setup, props, key) {
|
|
1125
1151
|
if (typeof setup === 'string') {
|
|
1126
|
-
return JSXElement.
|
|
1152
|
+
return JSXElement.createInstance(setup, props, key);
|
|
1127
1153
|
}
|
|
1128
|
-
return new JSXComponent(props, function (context
|
|
1154
|
+
return new JSXComponent(setup, props, function (context) {
|
|
1129
1155
|
return new Component(context, setup, props, key);
|
|
1130
|
-
});
|
|
1156
|
+
}, key);
|
|
1131
1157
|
}
|
|
1132
1158
|
const jsxs = jsx;
|
|
1159
|
+
const JSXTextTypeOf = Symbol('JSXText');
|
|
1133
1160
|
class JSXText {
|
|
1134
1161
|
constructor(text) {
|
|
1135
1162
|
this.text = text;
|
|
1136
|
-
this.$$typeOf =
|
|
1137
|
-
}
|
|
1138
|
-
is(target) {
|
|
1139
|
-
return target.$$typeOf === this.$$typeOf;
|
|
1163
|
+
this.$$typeOf = JSXTextTypeOf;
|
|
1140
1164
|
}
|
|
1141
1165
|
}
|
|
1142
1166
|
class JSXElement {
|
|
1143
|
-
static
|
|
1144
|
-
return new JSXElement(
|
|
1167
|
+
static createInstance(type, props, key) {
|
|
1168
|
+
return new JSXElement(type, props, key);
|
|
1145
1169
|
}
|
|
1146
1170
|
constructor(type, props, key) {
|
|
1147
1171
|
this.type = type;
|
|
@@ -1149,39 +1173,27 @@ class JSXElement {
|
|
|
1149
1173
|
this.key = key;
|
|
1150
1174
|
this.$$typeOf = this.type;
|
|
1151
1175
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1176
|
+
}
|
|
1177
|
+
class JSXComponent {
|
|
1178
|
+
constructor(type, props, factory, key) {
|
|
1179
|
+
this.type = type;
|
|
1180
|
+
this.props = props;
|
|
1181
|
+
this.factory = factory;
|
|
1182
|
+
this.key = key;
|
|
1183
|
+
this.$$typeOf = this.type;
|
|
1184
|
+
}
|
|
1185
|
+
createInstance(parentComponent) {
|
|
1186
|
+
return this.factory(parentComponent);
|
|
1154
1187
|
}
|
|
1155
1188
|
}
|
|
1156
1189
|
|
|
1157
|
-
function withMemo(
|
|
1190
|
+
function withMemo(canUseMemo, render) {
|
|
1158
1191
|
return {
|
|
1159
|
-
$
|
|
1192
|
+
$useMemo: canUseMemo,
|
|
1160
1193
|
$render: render
|
|
1161
1194
|
};
|
|
1162
1195
|
}
|
|
1163
1196
|
|
|
1164
|
-
/**
|
|
1165
|
-
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
1166
|
-
*/
|
|
1167
|
-
class RootComponent extends Component {
|
|
1168
|
-
constructor(parentInjector, factory) {
|
|
1169
|
-
super(parentInjector, factory, {});
|
|
1170
|
-
this.onChange = null;
|
|
1171
|
-
}
|
|
1172
|
-
markAsChanged(changedComponent) {
|
|
1173
|
-
var _a;
|
|
1174
|
-
this._changed = true;
|
|
1175
|
-
if (changedComponent) {
|
|
1176
|
-
this.changedSubComponents.add(changedComponent);
|
|
1177
|
-
}
|
|
1178
|
-
(_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
class NativeRenderer {
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
1197
|
function createRenderer(component, nativeRenderer) {
|
|
1186
1198
|
let isInit = true;
|
|
1187
1199
|
return function render(host) {
|
|
@@ -1194,7 +1206,7 @@ function createRenderer(component, nativeRenderer) {
|
|
|
1194
1206
|
child: null,
|
|
1195
1207
|
nativeNode: null
|
|
1196
1208
|
};
|
|
1197
|
-
|
|
1209
|
+
componentRender(nativeRenderer, component, atom, {
|
|
1198
1210
|
isParent: true,
|
|
1199
1211
|
host
|
|
1200
1212
|
});
|
|
@@ -1204,15 +1216,11 @@ function createRenderer(component, nativeRenderer) {
|
|
|
1204
1216
|
}
|
|
1205
1217
|
};
|
|
1206
1218
|
}
|
|
1207
|
-
function buildView(nativeRenderer, atom, context) {
|
|
1208
|
-
if (atom.jsxNode instanceof
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
buildView(nativeRenderer, child, context);
|
|
1213
|
-
child = child.sibling;
|
|
1214
|
-
}
|
|
1215
|
-
atom.jsxNode.rendered();
|
|
1219
|
+
function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
1220
|
+
if (atom.jsxNode instanceof JSXComponent) {
|
|
1221
|
+
const component = atom.jsxNode.createInstance(parentComponent);
|
|
1222
|
+
atom.jsxNode = component;
|
|
1223
|
+
componentRender(nativeRenderer, component, atom, context);
|
|
1216
1224
|
}
|
|
1217
1225
|
else {
|
|
1218
1226
|
let nativeNode;
|
|
@@ -1239,7 +1247,7 @@ function buildView(nativeRenderer, atom, context) {
|
|
|
1239
1247
|
};
|
|
1240
1248
|
let child = atom.child;
|
|
1241
1249
|
while (child) {
|
|
1242
|
-
buildView(nativeRenderer, child, childContext);
|
|
1250
|
+
buildView(nativeRenderer, parentComponent, child, childContext);
|
|
1243
1251
|
child = child.sibling;
|
|
1244
1252
|
}
|
|
1245
1253
|
}
|
|
@@ -1263,9 +1271,9 @@ function updateView(nativeRenderer, component) {
|
|
|
1263
1271
|
}
|
|
1264
1272
|
}
|
|
1265
1273
|
function applyChanges(nativeRenderer, component) {
|
|
1266
|
-
const { atom,
|
|
1274
|
+
const { atom, host, isParent } = component.$$view;
|
|
1267
1275
|
const diffAtom = atom.child;
|
|
1268
|
-
const template =
|
|
1276
|
+
const template = component.update(component.props, true);
|
|
1269
1277
|
if (template) {
|
|
1270
1278
|
linkTemplate(template, component, atom);
|
|
1271
1279
|
}
|
|
@@ -1276,34 +1284,48 @@ function applyChanges(nativeRenderer, component) {
|
|
|
1276
1284
|
host,
|
|
1277
1285
|
isParent
|
|
1278
1286
|
};
|
|
1279
|
-
diff(nativeRenderer, atom.child, diffAtom, context, 0, 0);
|
|
1287
|
+
diff(nativeRenderer, component, atom.child, diffAtom, context, 0, 0);
|
|
1280
1288
|
const next = atom.sibling;
|
|
1281
1289
|
if (next && next.jsxNode instanceof Component) {
|
|
1282
1290
|
next.jsxNode.$$view.host = context.host;
|
|
1283
1291
|
next.jsxNode.$$view.isParent = context.isParent;
|
|
1284
1292
|
}
|
|
1285
1293
|
}
|
|
1286
|
-
function diff(nativeRenderer, newAtom, oldAtom, context, expectIndex, index) {
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1294
|
+
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expectIndex, index) {
|
|
1295
|
+
let prevDiffAtom = null;
|
|
1296
|
+
let firstDiffAtomIndexed = null;
|
|
1297
|
+
if (oldAtom) {
|
|
1298
|
+
prevDiffAtom = {
|
|
1290
1299
|
index,
|
|
1291
|
-
atom: oldAtom
|
|
1292
|
-
|
|
1293
|
-
|
|
1300
|
+
atom: oldAtom,
|
|
1301
|
+
prev: null
|
|
1302
|
+
};
|
|
1294
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
|
+
}
|
|
1295
1317
|
}
|
|
1296
1318
|
const commits = [];
|
|
1297
1319
|
const changeCommits = {
|
|
1298
1320
|
updateComponent: (newAtom, reusedAtom, expectIndex, diffIndex) => {
|
|
1299
1321
|
commits.push((offset) => {
|
|
1300
|
-
const
|
|
1322
|
+
const instance = reusedAtom.jsxNode;
|
|
1301
1323
|
const newProps = newAtom.jsxNode.props;
|
|
1302
|
-
const
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
newAtom.jsxNode
|
|
1306
|
-
if (newTemplate ===
|
|
1324
|
+
const oldTemplate = instance.template;
|
|
1325
|
+
const newTemplate = instance.update(newProps);
|
|
1326
|
+
instance.$$view = Object.assign({ atom: newAtom }, context);
|
|
1327
|
+
newAtom.jsxNode = instance;
|
|
1328
|
+
if (newTemplate === oldTemplate) {
|
|
1307
1329
|
reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex !== diffIndex - offset);
|
|
1308
1330
|
return;
|
|
1309
1331
|
}
|
|
@@ -1311,7 +1333,7 @@ function diff(nativeRenderer, newAtom, oldAtom, context, expectIndex, index) {
|
|
|
1311
1333
|
linkTemplate(newTemplate, newAtom.jsxNode, newAtom);
|
|
1312
1334
|
}
|
|
1313
1335
|
if (newAtom.child) {
|
|
1314
|
-
diff(nativeRenderer, newAtom.child, reusedAtom.child, context, expectIndex, diffIndex);
|
|
1336
|
+
diff(nativeRenderer, instance, newAtom.child, reusedAtom.child, context, expectIndex, diffIndex);
|
|
1315
1337
|
}
|
|
1316
1338
|
else if (reusedAtom.child) {
|
|
1317
1339
|
let atom = reusedAtom.child;
|
|
@@ -1320,7 +1342,7 @@ function diff(nativeRenderer, newAtom, oldAtom, context, expectIndex, index) {
|
|
|
1320
1342
|
atom = atom.sibling;
|
|
1321
1343
|
}
|
|
1322
1344
|
}
|
|
1323
|
-
|
|
1345
|
+
instance.rendered();
|
|
1324
1346
|
});
|
|
1325
1347
|
},
|
|
1326
1348
|
updateElement: (newAtom, oldAtom, expectIndex, oldIndex) => {
|
|
@@ -1339,7 +1361,7 @@ function diff(nativeRenderer, newAtom, oldAtom, context, expectIndex, index) {
|
|
|
1339
1361
|
context.isParent = false;
|
|
1340
1362
|
const applyRefs = updateNativeNodeProperties(nativeRenderer, newAtom.jsxNode, oldAtom.jsxNode, newAtom.nativeNode);
|
|
1341
1363
|
if (newAtom.child) {
|
|
1342
|
-
diff(nativeRenderer, newAtom.child, oldAtom.child, {
|
|
1364
|
+
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, {
|
|
1343
1365
|
host: newAtom.nativeNode,
|
|
1344
1366
|
isParent: true
|
|
1345
1367
|
}, 0, 0);
|
|
@@ -1367,28 +1389,27 @@ function diff(nativeRenderer, newAtom, oldAtom, context, expectIndex, index) {
|
|
|
1367
1389
|
},
|
|
1368
1390
|
create: (start) => {
|
|
1369
1391
|
commits.push(() => {
|
|
1370
|
-
buildView(nativeRenderer, start, context);
|
|
1392
|
+
buildView(nativeRenderer, parentComponent, start, context);
|
|
1371
1393
|
});
|
|
1372
1394
|
}
|
|
1373
1395
|
};
|
|
1374
1396
|
while (newAtom) {
|
|
1375
|
-
createChanges(newAtom, expectIndex,
|
|
1397
|
+
firstDiffAtomIndexed = createChanges(newAtom, expectIndex, firstDiffAtomIndexed, changeCommits);
|
|
1376
1398
|
newAtom = newAtom.sibling;
|
|
1377
1399
|
expectIndex++;
|
|
1378
1400
|
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1401
|
+
let dirtyDiffAtom = firstDiffAtomIndexed;
|
|
1402
|
+
while (dirtyDiffAtom) {
|
|
1403
|
+
cleanView(nativeRenderer, dirtyDiffAtom.atom, false);
|
|
1404
|
+
dirtyDiffAtom = dirtyDiffAtom.next;
|
|
1381
1405
|
}
|
|
1382
|
-
let j = 0;
|
|
1383
1406
|
let offset = 0;
|
|
1384
|
-
const len = oldChildren.length;
|
|
1385
1407
|
for (let i = 0; i < commits.length; i++) {
|
|
1386
1408
|
const commit = commits[i];
|
|
1387
|
-
while (
|
|
1388
|
-
|
|
1389
|
-
if (current.index <= i) {
|
|
1409
|
+
while (firstDiffAtomIndexed) {
|
|
1410
|
+
if (firstDiffAtomIndexed.index <= i) {
|
|
1390
1411
|
offset++;
|
|
1391
|
-
|
|
1412
|
+
firstDiffAtomIndexed = firstDiffAtomIndexed.next;
|
|
1392
1413
|
continue;
|
|
1393
1414
|
}
|
|
1394
1415
|
break;
|
|
@@ -1430,17 +1451,19 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
|
|
|
1430
1451
|
updateContext(atom);
|
|
1431
1452
|
}
|
|
1432
1453
|
}
|
|
1433
|
-
function createChanges(newAtom, expectIndex,
|
|
1434
|
-
|
|
1435
|
-
|
|
1454
|
+
function createChanges(newAtom, expectIndex, diffAtomIndexed, changeCommits) {
|
|
1455
|
+
const startDiffAtom = diffAtomIndexed;
|
|
1456
|
+
while (diffAtomIndexed) {
|
|
1457
|
+
const { atom: diffAtom, index: diffIndex } = diffAtomIndexed;
|
|
1436
1458
|
const key = newAtom.jsxNode.key;
|
|
1437
1459
|
const diffKey = diffAtom.jsxNode.key;
|
|
1438
1460
|
if (key !== undefined && diffKey !== undefined) {
|
|
1439
1461
|
if (diffKey !== key) {
|
|
1462
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1440
1463
|
continue;
|
|
1441
1464
|
}
|
|
1442
1465
|
}
|
|
1443
|
-
if (newAtom.jsxNode
|
|
1466
|
+
if (newAtom.jsxNode.$$typeOf === diffAtom.jsxNode.$$typeOf) {
|
|
1444
1467
|
if (newAtom.jsxNode instanceof JSXElement) {
|
|
1445
1468
|
changeCommits.updateElement(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1446
1469
|
}
|
|
@@ -1450,11 +1473,25 @@ function createChanges(newAtom, expectIndex, oldChildren, changeCommits) {
|
|
|
1450
1473
|
else {
|
|
1451
1474
|
changeCommits.updateComponent(newAtom, diffAtom, expectIndex, diffIndex);
|
|
1452
1475
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
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;
|
|
1455
1490
|
}
|
|
1491
|
+
diffAtomIndexed = diffAtomIndexed.next;
|
|
1456
1492
|
}
|
|
1457
1493
|
changeCommits.create(newAtom);
|
|
1494
|
+
return startDiffAtom;
|
|
1458
1495
|
}
|
|
1459
1496
|
function cleanView(nativeRenderer, atom, isClean) {
|
|
1460
1497
|
if (atom.nativeNode) {
|
|
@@ -1476,26 +1513,29 @@ function cleanView(nativeRenderer, atom, isClean) {
|
|
|
1476
1513
|
atom.jsxNode.destroy();
|
|
1477
1514
|
}
|
|
1478
1515
|
}
|
|
1479
|
-
function componentRender(component, from, context) {
|
|
1480
|
-
const
|
|
1516
|
+
function componentRender(nativeRenderer, component, from, context) {
|
|
1517
|
+
const template = component.render();
|
|
1481
1518
|
if (template) {
|
|
1482
1519
|
linkTemplate(template, component, from);
|
|
1483
1520
|
}
|
|
1484
|
-
component.$$view = Object.assign({
|
|
1485
|
-
|
|
1486
|
-
|
|
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();
|
|
1487
1528
|
}
|
|
1488
|
-
function createChainByComponentFactory(
|
|
1489
|
-
const component = factory.createInstance(context);
|
|
1529
|
+
function createChainByComponentFactory(jsxComponent, parent) {
|
|
1490
1530
|
return {
|
|
1491
|
-
jsxNode:
|
|
1531
|
+
jsxNode: jsxComponent,
|
|
1492
1532
|
parent,
|
|
1493
1533
|
sibling: null,
|
|
1494
1534
|
child: null,
|
|
1495
1535
|
nativeNode: null
|
|
1496
1536
|
};
|
|
1497
1537
|
}
|
|
1498
|
-
function createChainByJSXElement(
|
|
1538
|
+
function createChainByJSXElement(component, element, parent) {
|
|
1499
1539
|
const atom = {
|
|
1500
1540
|
jsxNode: element,
|
|
1501
1541
|
parent,
|
|
@@ -1505,7 +1545,7 @@ function createChainByJSXElement(context, element, parent) {
|
|
|
1505
1545
|
};
|
|
1506
1546
|
if (Reflect.has(element.props, 'children')) {
|
|
1507
1547
|
const jsxChildren = element.props.children;
|
|
1508
|
-
const children = createChainByChildren(
|
|
1548
|
+
const children = createChainByChildren(component, Array.isArray(jsxChildren) ? jsxChildren : [jsxChildren], atom, []);
|
|
1509
1549
|
link(atom, children);
|
|
1510
1550
|
}
|
|
1511
1551
|
return atom;
|
|
@@ -1519,26 +1559,26 @@ function createChainByJSXText(node, parent) {
|
|
|
1519
1559
|
nativeNode: null
|
|
1520
1560
|
};
|
|
1521
1561
|
}
|
|
1522
|
-
function createChainByChildren(
|
|
1562
|
+
function createChainByChildren(component, children, parent, atoms) {
|
|
1523
1563
|
for (const item of children) {
|
|
1524
|
-
if (item instanceof JSXElement) {
|
|
1525
|
-
atoms.push(createChainByJSXElement(context, item, parent));
|
|
1526
|
-
continue;
|
|
1527
|
-
}
|
|
1528
|
-
if (item instanceof JSXComponent) {
|
|
1529
|
-
const childAtom = createChainByComponentFactory(context, item, parent);
|
|
1530
|
-
atoms.push(childAtom);
|
|
1531
|
-
continue;
|
|
1532
|
-
}
|
|
1533
|
-
if (typeof item === 'string' && item.length) {
|
|
1534
|
-
atoms.push(createChainByJSXText(new JSXText(item), parent));
|
|
1535
|
-
continue;
|
|
1536
|
-
}
|
|
1537
|
-
if (Array.isArray(item)) {
|
|
1538
|
-
createChainByChildren(context, item, parent, atoms);
|
|
1539
|
-
continue;
|
|
1540
|
-
}
|
|
1541
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
|
+
}
|
|
1542
1582
|
atoms.push(createChainByJSXText(new JSXText(String(item)), parent));
|
|
1543
1583
|
}
|
|
1544
1584
|
}
|
|
@@ -1546,7 +1586,8 @@ function createChainByChildren(context, children, parent, atoms) {
|
|
|
1546
1586
|
}
|
|
1547
1587
|
function linkTemplate(template, component, parent) {
|
|
1548
1588
|
const children = Array.isArray(template) ? template : [template];
|
|
1549
|
-
|
|
1589
|
+
const newChildren = createChainByChildren(component, children, parent, []);
|
|
1590
|
+
link(parent, newChildren);
|
|
1550
1591
|
}
|
|
1551
1592
|
function link(parent, children) {
|
|
1552
1593
|
for (let i = 1; i < children.length; i++) {
|
|
@@ -1726,6 +1767,24 @@ function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn) {
|
|
|
1726
1767
|
nativeRenderer.listen(nativeNode, type, delegate);
|
|
1727
1768
|
}
|
|
1728
1769
|
|
|
1770
|
+
/**
|
|
1771
|
+
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
1772
|
+
*/
|
|
1773
|
+
class RootComponent extends Component {
|
|
1774
|
+
constructor(parentInjector, factory) {
|
|
1775
|
+
super(parentInjector, factory, {});
|
|
1776
|
+
this.onChange = null;
|
|
1777
|
+
}
|
|
1778
|
+
markAsChanged(changedComponent) {
|
|
1779
|
+
var _a;
|
|
1780
|
+
this._changed = true;
|
|
1781
|
+
if (changedComponent) {
|
|
1782
|
+
this.changedSubComponents.add(changedComponent);
|
|
1783
|
+
}
|
|
1784
|
+
(_a = this.onChange) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1729
1788
|
const viewflyErrorFn = makeError('Viewfly');
|
|
1730
1789
|
function viewfly({ context, nativeRenderer, autoUpdate, root }) {
|
|
1731
1790
|
const appProviders = [];
|