@viewfly/core 1.0.4 → 1.1.0
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/index.d.ts +127 -124
- package/bundles/index.esm.js +211 -236
- package/bundles/index.js +213 -235
- package/package.json +2 -2
package/bundles/index.esm.js
CHANGED
|
@@ -570,23 +570,6 @@ function getObjectChanges(newProps, oldProps) {
|
|
|
570
570
|
}
|
|
571
571
|
return changes;
|
|
572
572
|
}
|
|
573
|
-
function getArrayChanges(left, right) {
|
|
574
|
-
const changes = {
|
|
575
|
-
add: [],
|
|
576
|
-
remove: []
|
|
577
|
-
};
|
|
578
|
-
for (const i of left) {
|
|
579
|
-
if (!right.includes(i)) {
|
|
580
|
-
changes.remove.push(i);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
for (const i of right) {
|
|
584
|
-
if (!left.includes(i)) {
|
|
585
|
-
changes.add.push(i);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return changes;
|
|
589
|
-
}
|
|
590
573
|
function classToString(config) {
|
|
591
574
|
if (typeof config === 'string') {
|
|
592
575
|
return config;
|
|
@@ -635,8 +618,28 @@ const TextAtomType = Symbol('Text');
|
|
|
635
618
|
const ElementAtomType = Symbol('Element');
|
|
636
619
|
const ComponentAtomType = Symbol('Component');
|
|
637
620
|
|
|
621
|
+
class Listener {
|
|
622
|
+
constructor(effect) {
|
|
623
|
+
this.effect = effect;
|
|
624
|
+
this.destroyCallbacks = [];
|
|
625
|
+
}
|
|
626
|
+
destroy() {
|
|
627
|
+
this.destroyCallbacks.forEach(fn => fn());
|
|
628
|
+
this.destroyCallbacks = [];
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
const listeners = [];
|
|
632
|
+
function getCurrentListener() {
|
|
633
|
+
return listeners.at(-1);
|
|
634
|
+
}
|
|
635
|
+
function pushListener(listener) {
|
|
636
|
+
listeners.push(listener);
|
|
637
|
+
}
|
|
638
|
+
function popListener() {
|
|
639
|
+
listeners.pop();
|
|
640
|
+
}
|
|
641
|
+
|
|
638
642
|
const componentSetupStack = [];
|
|
639
|
-
const signalDepsStack = [];
|
|
640
643
|
const componentErrorFn = makeError('component');
|
|
641
644
|
function getSetupContext(need = true) {
|
|
642
645
|
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
@@ -646,9 +649,6 @@ function getSetupContext(need = true) {
|
|
|
646
649
|
}
|
|
647
650
|
return current;
|
|
648
651
|
}
|
|
649
|
-
function getSignalDepsContext() {
|
|
650
|
-
return signalDepsStack[signalDepsStack.length - 1];
|
|
651
|
-
}
|
|
652
652
|
/**
|
|
653
653
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
654
654
|
*/
|
|
@@ -675,6 +675,9 @@ class Component extends ReflectiveInjector {
|
|
|
675
675
|
this._changed = true;
|
|
676
676
|
this.isFirstRendering = true;
|
|
677
677
|
this.refs = null;
|
|
678
|
+
this.listener = new Listener(() => {
|
|
679
|
+
this.markAsDirtied();
|
|
680
|
+
});
|
|
678
681
|
}
|
|
679
682
|
markAsDirtied() {
|
|
680
683
|
this._dirty = true;
|
|
@@ -728,12 +731,9 @@ class Component extends ReflectiveInjector {
|
|
|
728
731
|
}
|
|
729
732
|
isSetup = false;
|
|
730
733
|
componentSetupStack.pop();
|
|
731
|
-
|
|
734
|
+
pushListener(this.listener);
|
|
732
735
|
const template = this.instance.$render();
|
|
733
|
-
|
|
734
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
735
|
-
this.markAsDirtied();
|
|
736
|
-
});
|
|
736
|
+
popListener();
|
|
737
737
|
update(template, this.instance.$portalHost);
|
|
738
738
|
this.rendered();
|
|
739
739
|
}
|
|
@@ -772,13 +772,10 @@ class Component extends ReflectiveInjector {
|
|
|
772
772
|
return;
|
|
773
773
|
}
|
|
774
774
|
}
|
|
775
|
-
this.
|
|
776
|
-
|
|
775
|
+
this.listener.destroy();
|
|
776
|
+
pushListener(this.listener);
|
|
777
777
|
const template = this.instance.$render();
|
|
778
|
-
|
|
779
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
780
|
-
this.markAsDirtied();
|
|
781
|
-
});
|
|
778
|
+
popListener();
|
|
782
779
|
updateChildren(template);
|
|
783
780
|
this.rendered();
|
|
784
781
|
}
|
|
@@ -788,7 +785,7 @@ class Component extends ReflectiveInjector {
|
|
|
788
785
|
}
|
|
789
786
|
destroy() {
|
|
790
787
|
var _a, _b, _c;
|
|
791
|
-
this.
|
|
788
|
+
this.listener.destroy();
|
|
792
789
|
(_a = this.updatedDestroyCallbacks) === null || _a === void 0 ? void 0 : _a.forEach(fn => {
|
|
793
790
|
fn();
|
|
794
791
|
});
|
|
@@ -1050,173 +1047,6 @@ class StaticRef extends DynamicRef {
|
|
|
1050
1047
|
function createRef() {
|
|
1051
1048
|
return new StaticRef();
|
|
1052
1049
|
}
|
|
1053
|
-
const depsKey = Symbol('deps');
|
|
1054
|
-
/**
|
|
1055
|
-
* 组件状态管理器
|
|
1056
|
-
* @param state 初始状态
|
|
1057
|
-
* @example
|
|
1058
|
-
* ```tsx
|
|
1059
|
-
* function App() {
|
|
1060
|
-
* // 初始化状态
|
|
1061
|
-
* const state = createSignal(1)
|
|
1062
|
-
*
|
|
1063
|
-
* return () => {
|
|
1064
|
-
* <div>
|
|
1065
|
-
* <div>当前值为:{state()}</div>
|
|
1066
|
-
* <div>
|
|
1067
|
-
* <button type="button" onClick={() => {
|
|
1068
|
-
* // 当点击时更新状态
|
|
1069
|
-
* state.set(state() + 1)
|
|
1070
|
-
* }
|
|
1071
|
-
* }>updateState</button>
|
|
1072
|
-
* </div>
|
|
1073
|
-
* </div>
|
|
1074
|
-
* }
|
|
1075
|
-
* }
|
|
1076
|
-
*/
|
|
1077
|
-
function createSignal(state) {
|
|
1078
|
-
function signal() {
|
|
1079
|
-
const depsContext = getSignalDepsContext();
|
|
1080
|
-
if (depsContext) {
|
|
1081
|
-
depsContext.push(signal);
|
|
1082
|
-
}
|
|
1083
|
-
return state;
|
|
1084
|
-
}
|
|
1085
|
-
signal.$isSignal = true;
|
|
1086
|
-
signal.set = function (newState) {
|
|
1087
|
-
if (newState === state) {
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
state = newState;
|
|
1091
|
-
const depCallbacks = Array.from(signal[depsKey]);
|
|
1092
|
-
for (const fn of depCallbacks) {
|
|
1093
|
-
// 回调中可能会对依赖做出修改,故需先缓存起来
|
|
1094
|
-
fn();
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
//
|
|
1098
|
-
// signal.toString = function () {
|
|
1099
|
-
// return String(state)
|
|
1100
|
-
// }
|
|
1101
|
-
//
|
|
1102
|
-
// signal.valueOf = function () {
|
|
1103
|
-
// return state
|
|
1104
|
-
// }
|
|
1105
|
-
signal[depsKey] = new Set();
|
|
1106
|
-
return signal;
|
|
1107
|
-
}
|
|
1108
|
-
function invokeDepFn(fn) {
|
|
1109
|
-
const deps = [];
|
|
1110
|
-
signalDepsStack.push(deps);
|
|
1111
|
-
const data = fn();
|
|
1112
|
-
signalDepsStack.pop();
|
|
1113
|
-
return {
|
|
1114
|
-
deps: Array.from(new Set(deps)),
|
|
1115
|
-
data
|
|
1116
|
-
};
|
|
1117
|
-
}
|
|
1118
|
-
function listen(model, deps, callback, isContinue) {
|
|
1119
|
-
let isStop = false;
|
|
1120
|
-
const nextListen = () => {
|
|
1121
|
-
if (isStop) {
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
isStop = true;
|
|
1125
|
-
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
1126
|
-
model.set(nextData);
|
|
1127
|
-
if (typeof isContinue === 'function' && isContinue(nextData) === false) {
|
|
1128
|
-
unListen();
|
|
1129
|
-
return;
|
|
1130
|
-
}
|
|
1131
|
-
const changes = getArrayChanges(deps, nextDeps);
|
|
1132
|
-
deps = deps.filter(i => {
|
|
1133
|
-
const has = changes.remove.includes(i);
|
|
1134
|
-
if (has) {
|
|
1135
|
-
i[depsKey].delete(nextListen);
|
|
1136
|
-
return false;
|
|
1137
|
-
}
|
|
1138
|
-
return true;
|
|
1139
|
-
});
|
|
1140
|
-
for (const s of changes.add) {
|
|
1141
|
-
s[depsKey].add(nextListen);
|
|
1142
|
-
}
|
|
1143
|
-
deps.push(...changes.add);
|
|
1144
|
-
isStop = false;
|
|
1145
|
-
};
|
|
1146
|
-
const unListen = () => {
|
|
1147
|
-
for (const s of deps) {
|
|
1148
|
-
s[depsKey].delete(nextListen);
|
|
1149
|
-
}
|
|
1150
|
-
};
|
|
1151
|
-
for (const s of deps) {
|
|
1152
|
-
s[depsKey].add(nextListen);
|
|
1153
|
-
}
|
|
1154
|
-
return unListen;
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1158
|
-
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1159
|
-
*
|
|
1160
|
-
* @param callback
|
|
1161
|
-
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1162
|
-
*/
|
|
1163
|
-
function createDerived(callback, isContinue) {
|
|
1164
|
-
const { data, deps } = invokeDepFn(callback);
|
|
1165
|
-
const signal = createSignal(data);
|
|
1166
|
-
const component = getSetupContext(false);
|
|
1167
|
-
const unListen = listen(signal, deps, callback, isContinue);
|
|
1168
|
-
if (component) {
|
|
1169
|
-
if (!component.unmountedCallbacks) {
|
|
1170
|
-
component.unmountedCallbacks = [];
|
|
1171
|
-
}
|
|
1172
|
-
component.unmountedCallbacks.push(() => {
|
|
1173
|
-
unListen();
|
|
1174
|
-
});
|
|
1175
|
-
}
|
|
1176
|
-
return signal;
|
|
1177
|
-
}
|
|
1178
|
-
/* eslint-enable max-len*/
|
|
1179
|
-
function watch(deps, callback) {
|
|
1180
|
-
if (typeof deps === 'function' && !deps.$isSignal) {
|
|
1181
|
-
deps = createDerived(deps);
|
|
1182
|
-
}
|
|
1183
|
-
const signals = Array.isArray(deps) ? deps : [deps];
|
|
1184
|
-
let oldValues = signals.map(s => s());
|
|
1185
|
-
let prevCleanup;
|
|
1186
|
-
function effectCallback() {
|
|
1187
|
-
if (typeof prevCleanup === 'function') {
|
|
1188
|
-
prevCleanup();
|
|
1189
|
-
}
|
|
1190
|
-
const newValues = signals.map(s => s());
|
|
1191
|
-
prevCleanup = Array.isArray(deps) ? callback(newValues, oldValues) : callback(newValues[0], oldValues[0]);
|
|
1192
|
-
oldValues = newValues;
|
|
1193
|
-
}
|
|
1194
|
-
for (const dep of signals) {
|
|
1195
|
-
dep[depsKey].add(effectCallback);
|
|
1196
|
-
}
|
|
1197
|
-
const component = getSetupContext(false);
|
|
1198
|
-
let isClean = false;
|
|
1199
|
-
const destroyFn = () => {
|
|
1200
|
-
if (isClean) {
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
|
-
isClean = true;
|
|
1204
|
-
if (component === null || component === void 0 ? void 0 : component.unmountedCallbacks) {
|
|
1205
|
-
const index = component.unmountedCallbacks.indexOf(destroyFn);
|
|
1206
|
-
component.unmountedCallbacks.splice(index, 1);
|
|
1207
|
-
}
|
|
1208
|
-
for (const dep of signals) {
|
|
1209
|
-
dep[depsKey].delete(effectCallback);
|
|
1210
|
-
}
|
|
1211
|
-
};
|
|
1212
|
-
if (component) {
|
|
1213
|
-
if (!component.unmountedCallbacks) {
|
|
1214
|
-
component.unmountedCallbacks = [];
|
|
1215
|
-
}
|
|
1216
|
-
component.unmountedCallbacks.push(destroyFn);
|
|
1217
|
-
}
|
|
1218
|
-
return destroyFn;
|
|
1219
|
-
}
|
|
1220
1050
|
/**
|
|
1221
1051
|
* 给组件添加注解
|
|
1222
1052
|
* @param annotation
|
|
@@ -1266,10 +1096,21 @@ function Fragment(props) {
|
|
|
1266
1096
|
};
|
|
1267
1097
|
}
|
|
1268
1098
|
function Context(props) {
|
|
1269
|
-
|
|
1270
|
-
|
|
1099
|
+
function createContextComponent(providers) {
|
|
1100
|
+
return withAnnotation({
|
|
1101
|
+
providers,
|
|
1102
|
+
}, () => {
|
|
1103
|
+
return () => {
|
|
1104
|
+
return props.children;
|
|
1105
|
+
};
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
let contextComponent = createContextComponent(props.providers);
|
|
1109
|
+
onPropsChanged((newProps) => {
|
|
1110
|
+
contextComponent = createContextComponent(newProps.providers);
|
|
1111
|
+
});
|
|
1271
1112
|
return () => {
|
|
1272
|
-
return
|
|
1113
|
+
return jsx(contextComponent, {});
|
|
1273
1114
|
};
|
|
1274
1115
|
}
|
|
1275
1116
|
function jsx(type, props, key) {
|
|
@@ -1293,9 +1134,13 @@ function withMemo(canUseMemo, render) {
|
|
|
1293
1134
|
};
|
|
1294
1135
|
}
|
|
1295
1136
|
|
|
1137
|
+
const ElementNamespaceMap = {
|
|
1138
|
+
svg: 'svg',
|
|
1139
|
+
math: 'mathml',
|
|
1140
|
+
};
|
|
1296
1141
|
const componentViewCache = new WeakMap();
|
|
1297
1142
|
const listenerReg = /^on[A-Z]/;
|
|
1298
|
-
function createRenderer(component, nativeRenderer) {
|
|
1143
|
+
function createRenderer(component, nativeRenderer, namespace) {
|
|
1299
1144
|
let isInit = true;
|
|
1300
1145
|
return function render(host) {
|
|
1301
1146
|
if (isInit) {
|
|
@@ -1308,7 +1153,7 @@ function createRenderer(component, nativeRenderer) {
|
|
|
1308
1153
|
sibling: null,
|
|
1309
1154
|
child: null,
|
|
1310
1155
|
nativeNode: null,
|
|
1311
|
-
|
|
1156
|
+
namespace
|
|
1312
1157
|
};
|
|
1313
1158
|
componentRender(nativeRenderer, component, atom, {
|
|
1314
1159
|
isParent: true,
|
|
@@ -1361,7 +1206,7 @@ function updateView(nativeRenderer, component, needMove) {
|
|
|
1361
1206
|
function applyChanges(nativeRenderer, component, atom, context, needMove) {
|
|
1362
1207
|
const diffAtom = atom.child;
|
|
1363
1208
|
component.update(component.props, newTemplate => {
|
|
1364
|
-
atom.child = createChildChain(newTemplate, atom.
|
|
1209
|
+
atom.child = createChildChain(newTemplate, atom.namespace);
|
|
1365
1210
|
diff(nativeRenderer, component, atom.child, diffAtom, context, needMove);
|
|
1366
1211
|
const next = atom.sibling;
|
|
1367
1212
|
if (next && next.jsxNode instanceof Component) {
|
|
@@ -1474,7 +1319,7 @@ function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
|
|
|
1474
1319
|
newAtom.jsxNode = component;
|
|
1475
1320
|
component.update(newProps, newTemplate => {
|
|
1476
1321
|
if (newTemplate) {
|
|
1477
|
-
newAtom.child = createChildChain(newTemplate, newAtom.
|
|
1322
|
+
newAtom.child = createChildChain(newTemplate, newAtom.namespace);
|
|
1478
1323
|
}
|
|
1479
1324
|
if (newAtom.child) {
|
|
1480
1325
|
diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
|
|
@@ -1534,7 +1379,7 @@ function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponen
|
|
|
1534
1379
|
}
|
|
1535
1380
|
function cleanElementChildren(atom, nativeRenderer) {
|
|
1536
1381
|
let child = atom.child;
|
|
1537
|
-
nativeRenderer.cleanChildren(atom.nativeNode, atom.
|
|
1382
|
+
nativeRenderer.cleanChildren(atom.nativeNode, atom.namespace);
|
|
1538
1383
|
while (child) {
|
|
1539
1384
|
cleanView(nativeRenderer, child, false);
|
|
1540
1385
|
child = child.sibling;
|
|
@@ -1543,7 +1388,7 @@ function cleanElementChildren(atom, nativeRenderer) {
|
|
|
1543
1388
|
function cleanView(nativeRenderer, atom, needClean) {
|
|
1544
1389
|
if (atom.nativeNode) {
|
|
1545
1390
|
if (needClean) {
|
|
1546
|
-
nativeRenderer.remove(atom.nativeNode, atom.
|
|
1391
|
+
nativeRenderer.remove(atom.nativeNode, atom.namespace);
|
|
1547
1392
|
needClean = false;
|
|
1548
1393
|
}
|
|
1549
1394
|
if (atom.type === ElementAtomType) {
|
|
@@ -1565,7 +1410,7 @@ function cleanView(nativeRenderer, atom, needClean) {
|
|
|
1565
1410
|
}
|
|
1566
1411
|
function componentRender(nativeRenderer, component, from, context) {
|
|
1567
1412
|
component.render((template, portalHost) => {
|
|
1568
|
-
from.child = createChildChain(template, from.
|
|
1413
|
+
from.child = createChildChain(template, from.namespace);
|
|
1569
1414
|
context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
|
|
1570
1415
|
componentViewCache.set(component, Object.assign({ atom: from }, context));
|
|
1571
1416
|
let child = from.child;
|
|
@@ -1575,7 +1420,7 @@ function componentRender(nativeRenderer, component, from, context) {
|
|
|
1575
1420
|
}
|
|
1576
1421
|
});
|
|
1577
1422
|
}
|
|
1578
|
-
function createChainByJSXNode(type, jsxNode, nodeType, prevAtom,
|
|
1423
|
+
function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key) {
|
|
1579
1424
|
const atom = {
|
|
1580
1425
|
type,
|
|
1581
1426
|
index: prevAtom.index + 1,
|
|
@@ -1583,88 +1428,88 @@ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, isSvg, key) {
|
|
|
1583
1428
|
sibling: null,
|
|
1584
1429
|
child: null,
|
|
1585
1430
|
nativeNode: null,
|
|
1586
|
-
|
|
1431
|
+
namespace,
|
|
1587
1432
|
nodeType,
|
|
1588
1433
|
key
|
|
1589
1434
|
};
|
|
1590
1435
|
prevAtom.sibling = atom;
|
|
1591
1436
|
return atom;
|
|
1592
1437
|
}
|
|
1593
|
-
function createChainByNode(jsxNode, prevAtom,
|
|
1438
|
+
function createChainByNode(jsxNode, prevAtom, elementNamespace) {
|
|
1594
1439
|
const type = typeof jsxNode;
|
|
1595
1440
|
if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
|
|
1596
1441
|
if (typeof jsxNode === 'string') {
|
|
1597
|
-
return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom,
|
|
1442
|
+
return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, elementNamespace);
|
|
1598
1443
|
}
|
|
1599
1444
|
if (Array.isArray(jsxNode)) {
|
|
1600
|
-
return createChainByChildren(jsxNode, prevAtom,
|
|
1445
|
+
return createChainByChildren(jsxNode, prevAtom, elementNamespace);
|
|
1601
1446
|
}
|
|
1602
1447
|
if (type === 'object') {
|
|
1603
1448
|
const nodeType = typeof jsxNode.type;
|
|
1604
1449
|
if (nodeType === 'string') {
|
|
1605
|
-
return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom,
|
|
1450
|
+
return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace || ElementNamespaceMap[jsxNode.type], jsxNode.key);
|
|
1606
1451
|
}
|
|
1607
1452
|
else if (nodeType === 'function') {
|
|
1608
|
-
return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom,
|
|
1453
|
+
return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom, ElementNamespaceMap[jsxNode.type], jsxNode.key);
|
|
1609
1454
|
}
|
|
1610
1455
|
}
|
|
1611
1456
|
const text = String(jsxNode);
|
|
1612
|
-
return createChainByJSXNode(TextAtomType, text, text, prevAtom,
|
|
1457
|
+
return createChainByJSXNode(TextAtomType, text, text, prevAtom, ElementNamespaceMap[jsxNode.type]);
|
|
1613
1458
|
}
|
|
1614
1459
|
return prevAtom;
|
|
1615
1460
|
}
|
|
1616
|
-
function createChainByChildren(children, prevAtom,
|
|
1461
|
+
function createChainByChildren(children, prevAtom, elementNamespace) {
|
|
1617
1462
|
for (const item of children) {
|
|
1618
|
-
prevAtom = createChainByNode(item, prevAtom,
|
|
1463
|
+
prevAtom = createChainByNode(item, prevAtom, elementNamespace);
|
|
1619
1464
|
}
|
|
1620
1465
|
return prevAtom;
|
|
1621
1466
|
}
|
|
1622
|
-
function createChildChain(template,
|
|
1467
|
+
function createChildChain(template, namespace) {
|
|
1623
1468
|
const beforeAtom = { sibling: null, index: -1 };
|
|
1624
|
-
createChainByNode(template, beforeAtom,
|
|
1469
|
+
createChainByNode(template, beforeAtom, namespace);
|
|
1625
1470
|
return beforeAtom.sibling;
|
|
1626
1471
|
}
|
|
1627
1472
|
function insertNode(nativeRenderer, atom, context) {
|
|
1628
1473
|
if (context.isParent) {
|
|
1629
1474
|
if (context.host === context.rootHost) {
|
|
1630
|
-
nativeRenderer.appendChild(context.host, atom.nativeNode, atom.
|
|
1475
|
+
nativeRenderer.appendChild(context.host, atom.nativeNode, atom.namespace);
|
|
1631
1476
|
}
|
|
1632
1477
|
else {
|
|
1633
|
-
nativeRenderer.prependChild(context.host, atom.nativeNode, atom.
|
|
1478
|
+
nativeRenderer.prependChild(context.host, atom.nativeNode, atom.namespace);
|
|
1634
1479
|
}
|
|
1635
1480
|
}
|
|
1636
1481
|
else {
|
|
1637
|
-
nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.
|
|
1482
|
+
nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
|
|
1638
1483
|
}
|
|
1639
1484
|
}
|
|
1640
1485
|
function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
1641
|
-
const {
|
|
1642
|
-
const nativeNode = nativeRenderer.createElement(jsxNode.type,
|
|
1486
|
+
const { namespace, jsxNode } = atom;
|
|
1487
|
+
const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
|
|
1643
1488
|
const props = jsxNode.props;
|
|
1644
1489
|
let bindingRefs;
|
|
1645
1490
|
for (const key in props) {
|
|
1646
1491
|
if (key === 'children') {
|
|
1647
|
-
atom.child = createChildChain(jsxNode.props.children,
|
|
1492
|
+
atom.child = createChildChain(jsxNode.props.children, namespace);
|
|
1648
1493
|
continue;
|
|
1649
1494
|
}
|
|
1650
1495
|
if (key === 'class') {
|
|
1651
1496
|
const className = classToString(props[key]);
|
|
1652
1497
|
if (className) {
|
|
1653
|
-
nativeRenderer.setClass(nativeNode, className,
|
|
1498
|
+
nativeRenderer.setClass(nativeNode, className, namespace);
|
|
1654
1499
|
}
|
|
1655
1500
|
continue;
|
|
1656
1501
|
}
|
|
1657
1502
|
if (key === 'style') {
|
|
1658
1503
|
const style = styleToObject(props.style);
|
|
1659
1504
|
for (const key in style) {
|
|
1660
|
-
nativeRenderer.setStyle(nativeNode, key, style[key],
|
|
1505
|
+
nativeRenderer.setStyle(nativeNode, key, style[key], namespace);
|
|
1661
1506
|
}
|
|
1662
1507
|
continue;
|
|
1663
1508
|
}
|
|
1664
1509
|
if (listenerReg.test(key)) {
|
|
1665
1510
|
const listener = props[key];
|
|
1666
1511
|
if (typeof listener === 'function') {
|
|
1667
|
-
nativeRenderer.listen(nativeNode, key, listener,
|
|
1512
|
+
nativeRenderer.listen(nativeNode, key, listener, namespace);
|
|
1668
1513
|
}
|
|
1669
1514
|
continue;
|
|
1670
1515
|
}
|
|
@@ -1672,7 +1517,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
|
1672
1517
|
bindingRefs = props[key];
|
|
1673
1518
|
continue;
|
|
1674
1519
|
}
|
|
1675
|
-
nativeRenderer.setProperty(nativeNode, key, props[key],
|
|
1520
|
+
nativeRenderer.setProperty(nativeNode, key, props[key], namespace);
|
|
1676
1521
|
}
|
|
1677
1522
|
atom.nativeNode = nativeNode;
|
|
1678
1523
|
insertNode(nativeRenderer, atom, context);
|
|
@@ -1686,7 +1531,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
|
1686
1531
|
applyRefs(bindingRefs, nativeNode, true);
|
|
1687
1532
|
}
|
|
1688
1533
|
function createTextNode(nativeRenderer, atom, context) {
|
|
1689
|
-
const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.
|
|
1534
|
+
const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
|
|
1690
1535
|
atom.nativeNode = nativeNode;
|
|
1691
1536
|
insertNode(nativeRenderer, atom, context);
|
|
1692
1537
|
context.host = nativeNode;
|
|
@@ -1694,7 +1539,7 @@ function createTextNode(nativeRenderer, atom, context) {
|
|
|
1694
1539
|
}
|
|
1695
1540
|
function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context) {
|
|
1696
1541
|
const newVNode = newAtom.jsxNode;
|
|
1697
|
-
const isSvg = newAtom.
|
|
1542
|
+
const isSvg = newAtom.namespace;
|
|
1698
1543
|
const nativeNode = newAtom.nativeNode;
|
|
1699
1544
|
const oldVNode = oldAtom.jsxNode;
|
|
1700
1545
|
if (newVNode === oldVNode) {
|
|
@@ -1741,6 +1586,9 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1741
1586
|
if (!newAtom.child) {
|
|
1742
1587
|
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1743
1588
|
}
|
|
1589
|
+
else if (!oldAtom.child) {
|
|
1590
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
1591
|
+
}
|
|
1744
1592
|
else {
|
|
1745
1593
|
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
1746
1594
|
}
|
|
@@ -1841,6 +1689,133 @@ class RootComponent extends Component {
|
|
|
1841
1689
|
}
|
|
1842
1690
|
}
|
|
1843
1691
|
|
|
1692
|
+
/**
|
|
1693
|
+
* 组件状态管理器
|
|
1694
|
+
* @param state 初始状态
|
|
1695
|
+
* @example
|
|
1696
|
+
* ```tsx
|
|
1697
|
+
* function App() {
|
|
1698
|
+
* // 初始化状态
|
|
1699
|
+
* const state = createSignal(1)
|
|
1700
|
+
*
|
|
1701
|
+
* return () => {
|
|
1702
|
+
* <div>
|
|
1703
|
+
* <div>当前值为:{state()}</div>
|
|
1704
|
+
* <div>
|
|
1705
|
+
* <button type="button" onClick={() => {
|
|
1706
|
+
* // 当点击时更新状态
|
|
1707
|
+
* state.set(state() + 1)
|
|
1708
|
+
* }
|
|
1709
|
+
* }>updateState</button>
|
|
1710
|
+
* </div>
|
|
1711
|
+
* </div>
|
|
1712
|
+
* }
|
|
1713
|
+
* }
|
|
1714
|
+
*/
|
|
1715
|
+
function createSignal(state) {
|
|
1716
|
+
const subscribers = new Set();
|
|
1717
|
+
function signal() {
|
|
1718
|
+
const listener = getCurrentListener();
|
|
1719
|
+
if (listener) {
|
|
1720
|
+
listener.destroyCallbacks.push(() => {
|
|
1721
|
+
subscribers.delete(listener);
|
|
1722
|
+
});
|
|
1723
|
+
subscribers.add(listener);
|
|
1724
|
+
}
|
|
1725
|
+
return state;
|
|
1726
|
+
}
|
|
1727
|
+
signal.set = function (newValue) {
|
|
1728
|
+
if (newValue === state) {
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
state = newValue;
|
|
1732
|
+
const listeners = Array.from(subscribers);
|
|
1733
|
+
listeners.forEach(listener => listener.effect());
|
|
1734
|
+
};
|
|
1735
|
+
return signal;
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1739
|
+
* 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1740
|
+
*
|
|
1741
|
+
* @param fn
|
|
1742
|
+
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1743
|
+
*/
|
|
1744
|
+
function computed(fn, isContinue) {
|
|
1745
|
+
let isStop = false;
|
|
1746
|
+
function canListen(value) {
|
|
1747
|
+
if (isContinue) {
|
|
1748
|
+
const b = isContinue(value);
|
|
1749
|
+
if (b === false) {
|
|
1750
|
+
listener.destroy();
|
|
1751
|
+
return false;
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
return true;
|
|
1755
|
+
}
|
|
1756
|
+
const listener = new Listener(() => {
|
|
1757
|
+
if (isStop) {
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
isStop = true;
|
|
1761
|
+
listener.destroy();
|
|
1762
|
+
pushListener(listener);
|
|
1763
|
+
const value = fn();
|
|
1764
|
+
popListener();
|
|
1765
|
+
signal.set(value);
|
|
1766
|
+
canListen(value);
|
|
1767
|
+
isStop = false;
|
|
1768
|
+
});
|
|
1769
|
+
pushListener(listener);
|
|
1770
|
+
const value = fn();
|
|
1771
|
+
const signal = createSignal(value);
|
|
1772
|
+
popListener();
|
|
1773
|
+
isStop = false;
|
|
1774
|
+
if (canListen(value)) {
|
|
1775
|
+
registryComponentDestroyCallback(() => listener.destroy());
|
|
1776
|
+
}
|
|
1777
|
+
return signal;
|
|
1778
|
+
}
|
|
1779
|
+
const createDerived = computed;
|
|
1780
|
+
/* eslint-enable max-len*/
|
|
1781
|
+
function watch(deps, callback) {
|
|
1782
|
+
let prevFn;
|
|
1783
|
+
const isArray = Array.isArray(deps);
|
|
1784
|
+
const effect = new Listener(function () {
|
|
1785
|
+
if (prevFn) {
|
|
1786
|
+
prevFn();
|
|
1787
|
+
}
|
|
1788
|
+
const newValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1789
|
+
prevFn = callback(newValue, oldValue);
|
|
1790
|
+
oldValue = newValue;
|
|
1791
|
+
});
|
|
1792
|
+
pushListener(effect);
|
|
1793
|
+
let oldValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1794
|
+
popListener();
|
|
1795
|
+
let isUnWatch = false;
|
|
1796
|
+
function unWatch() {
|
|
1797
|
+
if (isUnWatch) {
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
isUnWatch = true;
|
|
1801
|
+
if (prevFn) {
|
|
1802
|
+
prevFn();
|
|
1803
|
+
}
|
|
1804
|
+
effect.destroy();
|
|
1805
|
+
}
|
|
1806
|
+
registryComponentDestroyCallback(unWatch);
|
|
1807
|
+
return unWatch;
|
|
1808
|
+
}
|
|
1809
|
+
function registryComponentDestroyCallback(fn) {
|
|
1810
|
+
const component = getSetupContext(false);
|
|
1811
|
+
if (component) {
|
|
1812
|
+
if (!component.unmountedCallbacks) {
|
|
1813
|
+
component.unmountedCallbacks = [];
|
|
1814
|
+
}
|
|
1815
|
+
component.unmountedCallbacks.push(fn);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1844
1819
|
const viewflyErrorFn = makeError('Viewfly');
|
|
1845
1820
|
function viewfly(config) {
|
|
1846
1821
|
const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
|
|
@@ -1864,7 +1839,7 @@ function viewfly(config) {
|
|
|
1864
1839
|
render(appHost);
|
|
1865
1840
|
});
|
|
1866
1841
|
});
|
|
1867
|
-
const render = createRenderer(rootComponent, nativeRenderer);
|
|
1842
|
+
const render = createRenderer(rootComponent, nativeRenderer, config.elementNamespace);
|
|
1868
1843
|
let isStarted = false;
|
|
1869
1844
|
let task = null;
|
|
1870
1845
|
function nextTick(callback) {
|
|
@@ -1928,4 +1903,4 @@ function viewfly(config) {
|
|
|
1928
1903
|
return app;
|
|
1929
1904
|
}
|
|
1930
1905
|
|
|
1931
|
-
export { Component, Context, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
|
1906
|
+
export { Component, Context, DynamicRef, ElementNamespaceMap, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, computed, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, getSetupContext, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|