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