@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.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
- signalDepsStack.push([]);
736
+ pushListener(this.listener);
734
737
  const template = this.instance.$render();
735
- const deps = signalDepsStack.pop();
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.unWatch();
778
- signalDepsStack.push([]);
777
+ this.listener.destroy();
778
+ pushListener(this.listener);
779
779
  const template = this.instance.$render();
780
- const deps = signalDepsStack.pop();
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.unWatch();
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
- const instance = getCurrentInstance();
1272
- instance.provide(props.providers);
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 props.children;
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
- isSvg: false
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.isSvg);
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.isSvg);
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.isSvg);
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.isSvg);
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.isSvg);
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, isSvg, key) {
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
- isSvg,
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, isSvg) {
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, isSvg);
1444
+ return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, elementNamespace);
1600
1445
  }
1601
1446
  if (Array.isArray(jsxNode)) {
1602
- return createChainByChildren(jsxNode, prevAtom, isSvg);
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, isSvg || jsxNode.type === 'svg', jsxNode.key);
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, isSvg, jsxNode.key);
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, isSvg);
1459
+ return createChainByJSXNode(TextAtomType, text, text, prevAtom, ElementNamespaceMap[jsxNode.type]);
1615
1460
  }
1616
1461
  return prevAtom;
1617
1462
  }
1618
- function createChainByChildren(children, prevAtom, isSvg) {
1463
+ function createChainByChildren(children, prevAtom, elementNamespace) {
1619
1464
  for (const item of children) {
1620
- prevAtom = createChainByNode(item, prevAtom, isSvg);
1465
+ prevAtom = createChainByNode(item, prevAtom, elementNamespace);
1621
1466
  }
1622
1467
  return prevAtom;
1623
1468
  }
1624
- function createChildChain(template, isSvg) {
1469
+ function createChildChain(template, namespace) {
1625
1470
  const beforeAtom = { sibling: null, index: -1 };
1626
- createChainByNode(template, beforeAtom, isSvg);
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.isSvg);
1477
+ nativeRenderer.appendChild(context.host, atom.nativeNode, atom.namespace);
1633
1478
  }
1634
1479
  else {
1635
- nativeRenderer.prependChild(context.host, atom.nativeNode, atom.isSvg);
1480
+ nativeRenderer.prependChild(context.host, atom.nativeNode, atom.namespace);
1636
1481
  }
1637
1482
  }
1638
1483
  else {
1639
- nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.isSvg);
1484
+ nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
1640
1485
  }
1641
1486
  }
1642
1487
  function createElement(nativeRenderer, atom, parentComponent, context) {
1643
- const { isSvg, jsxNode } = atom;
1644
- const nativeNode = nativeRenderer.createElement(jsxNode.type, isSvg);
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, isSvg);
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, isSvg);
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], isSvg);
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, isSvg);
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], isSvg);
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.isSvg);
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.isSvg;
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;