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