@viewfly/core 2.2.0 → 3.0.0-alpha.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/dist/index.esm.js CHANGED
@@ -441,12 +441,17 @@ var Type = Function;
441
441
  //#endregion
442
442
  //#region src/base/lifecycle.ts
443
443
  /**
444
- * 当组件第一次渲染完成时触发
445
- * @param callback
444
+ * 当组件挂载后调用回调函数
445
+ * @param callback 回调函数
446
+ * @returns 一个函数,用于停止监听
447
+ * @example
446
448
  * ```tsx
447
449
  * function App() {
448
- * onMount(() => {
450
+ * onMounted(() => {
449
451
  * console.log('App mounted!')
452
+ * return () => {
453
+ * console.log('destroy prev mount!')
454
+ * }
450
455
  * })
451
456
  * return () => <div>...</div>
452
457
  * }
@@ -458,8 +463,10 @@ function onMounted(callback) {
458
463
  component.mountCallbacks.push(callback);
459
464
  }
460
465
  /**
461
- * 当组件视图更新后调用
462
- * @param callback
466
+ * 当组件视图更新后调用回调函数
467
+ * @param callback 回调函数
468
+ * @returns 一个函数,用于停止监听
469
+ * @example
463
470
  * ```tsx
464
471
  * function App() {
465
472
  * onUpdated(() => {
@@ -482,76 +489,23 @@ function onUpdated(callback) {
482
489
  };
483
490
  }
484
491
  /**
485
- * 当组件销毁时调用回调函数
486
- * @param callback
487
- */
488
- function onUnmounted(callback) {
489
- const component = getSetupContext();
490
- if (!component.unmountedCallbacks) component.unmountedCallbacks = [];
491
- component.unmountedCallbacks.push(callback);
492
- }
493
- //#endregion
494
- //#region src/base/ref.ts
495
- var DynamicRef = class {
496
- unBindMap = /* @__PURE__ */ new Map();
497
- targetCaches = /* @__PURE__ */ new Set();
498
- constructor(callback) {
499
- this.callback = callback;
500
- }
501
- bind(value) {
502
- if (typeof value !== "object" || value === null) return;
503
- if (this.targetCaches.has(value)) return;
504
- const unBindFn = this.callback(value);
505
- if (typeof unBindFn === "function") this.unBindMap.set(value, unBindFn);
506
- this.targetCaches.add(value);
507
- }
508
- unBind(value) {
509
- this.targetCaches.delete(value);
510
- const unBindFn = this.unBindMap.get(value);
511
- this.unBindMap.delete(value);
512
- if (typeof unBindFn === "function") unBindFn();
513
- }
514
- };
515
- /**
516
- * 用于节点渲染完成时获取 DOM 节点
517
- * @param callback 获取 DOM 节点的回调函数
492
+ * 当组件销毁后调用回调函数
493
+ * @param callback 回调函数
494
+ * @returns 一个函数,用于停止监听
518
495
  * @example
519
496
  * ```tsx
520
497
  * function App() {
521
- * const ref = createDynamicRef(node => {
522
- * function fn() {
523
- * // do something...
524
- * }
525
- * node.addEventListener('click', fn)
526
- * return () => {
527
- * node.removeEventListener('click', fn)
528
- * }
498
+ * onUnmounted(() => {
499
+ * console.log('App unmounted!')
529
500
  * })
530
- * return () => {
531
- * return <div ref={ref}>xxx</div>
532
- * }
501
+ * return () => <div>...</div>
533
502
  * }
534
503
  * ```
535
504
  */
536
- function createDynamicRef(callback) {
537
- return new DynamicRef(callback);
538
- }
539
- var StaticRef = class extends DynamicRef {
540
- get current() {
541
- return this._current;
542
- }
543
- _current = null;
544
- constructor() {
545
- super((v) => {
546
- this._current = v;
547
- return () => {
548
- this._current = null;
549
- };
550
- });
551
- }
552
- };
553
- function createRef() {
554
- return new StaticRef();
505
+ function onUnmounted(callback) {
506
+ const component = getSetupContext();
507
+ if (!component.unmountedCallbacks) component.unmountedCallbacks = [];
508
+ component.unmountedCallbacks.push(callback);
555
509
  }
556
510
  //#endregion
557
511
  //#region src/reactive/_help.ts
@@ -907,14 +861,45 @@ function createSetHandlers(wrapper) {
907
861
  var reactiveErrorFn = makeError("reactive");
908
862
  var rawToProxyCache = /* @__PURE__ */ new WeakMap();
909
863
  var proxyToRawCache = /* @__PURE__ */ new WeakMap();
864
+ /**
865
+ * 将响应式对象转换为原始对象
866
+ * @param value 响应式对象
867
+ * @returns 原始对象
868
+ * @example
869
+ * ```tsx
870
+ * const obj = reactive({
871
+ * name: 'John',
872
+ * age: 18
873
+ * })
874
+ * console.log(toRaw(obj))
875
+ * ```
876
+ */
910
877
  function toRaw(value) {
911
878
  if (proxyToRawCache.has(value)) return proxyToRawCache.get(value);
912
879
  return value;
913
880
  }
881
+ /**
882
+ * 检查对象是否是响应式对象
883
+ * @param value 要检查的对象
884
+ * @returns 是否是响应式对象
885
+ * @example
886
+ * ```tsx
887
+ * const obj = reactive({
888
+ * name: 'John',
889
+ * age: 18
890
+ * })
891
+ * console.log(isReactive(obj))
892
+ * ```
893
+ */
914
894
  function isReactive(value) {
915
895
  return proxyToRawCache.has(value);
916
896
  }
917
897
  var fromInternalWrite = false;
898
+ /**
899
+ * 内部写入,用于避免类型为只读的响应式对象写入报错
900
+ * @param fn 要执行的函数
901
+ * @internal
902
+ */
918
903
  function internalWrite(fn) {
919
904
  fromInternalWrite = true;
920
905
  fn();
@@ -1016,6 +1001,29 @@ var readonlyProxyHandler = new ObjectReactiveHandler({
1016
1001
  shallow: true,
1017
1002
  readonly: true
1018
1003
  });
1004
+ function createShallowReadonlyProxy(value) {
1005
+ return new Proxy(value, readonlyProxyHandler);
1006
+ }
1007
+ /**
1008
+ * 创建一个响应式对象
1009
+ * @param raw 原始对象
1010
+ * @returns 响应式对象
1011
+ * @example
1012
+ * ```tsx
1013
+ * const obj = reactive({
1014
+ * name: 'John',
1015
+ * age: 18,
1016
+ * children: [
1017
+ * {
1018
+ * name: 'Jane',
1019
+ * age: 16
1020
+ * }
1021
+ * ]
1022
+ * })
1023
+ * console.log(obj.name)
1024
+ * console.log(obj.children[0].name)
1025
+ * ```
1026
+ */
1019
1027
  function reactive(raw) {
1020
1028
  if (isReactive(raw)) return raw;
1021
1029
  let proxy = rawToProxyCache.get(raw);
@@ -1091,6 +1099,97 @@ var TextAtomType = Symbol("Text");
1091
1099
  var ElementAtomType = Symbol("Element");
1092
1100
  var ComponentAtomType = Symbol("Component");
1093
1101
  //#endregion
1102
+ //#region src/base/ref.ts
1103
+ var refErrorFn = makeError("Ref");
1104
+ /**
1105
+ * 创建一个动态 ref,当 ref 的绑定的元素或组件初始化后,会调用副作用函数,并把元素或组件的实例作为参数传入。
1106
+ * @param effect 用于接收实例的副作用函数,该函数还可以返回一个清理副作用的函数,当元素或组件销毁时调用
1107
+ * @returns 一个函数,用于清理副作用
1108
+ * @example
1109
+ * ```tsx
1110
+ * function App() {
1111
+ * const ref = createDynamicRef<HTMLDivElement>((node) => {
1112
+ * console.log(node)
1113
+ * return () => {
1114
+ * console.log('destroy')
1115
+ * }
1116
+ * })
1117
+ * return () => {
1118
+ * return <div ref={ref}>test</div>
1119
+ * }
1120
+ * }
1121
+ * ```
1122
+ */
1123
+ function createDynamicRef(effect) {
1124
+ return effect;
1125
+ }
1126
+ /**
1127
+ * 创建一个引用对象,并添加到 JSX 节点上属性上,当组件渲染后,即可通过 .value 获取到绑定节点的实例
1128
+ * - 当绑定到虚拟 DOM 元素节点上时,value 为当前节点的 DOM 元素
1129
+ * - 当绑定到组件节点上时,value 为组件函数返回的对象
1130
+ * @example
1131
+ * ```tsx
1132
+ * function App() {
1133
+ * const ref = createRef<HTMLDivElement>()
1134
+ * onMounted(() => {
1135
+ * console.log(ref.value)
1136
+ * })
1137
+ * return () => {
1138
+ * return <div ref={ref}>...</div>
1139
+ * }
1140
+ * }
1141
+ * ```
1142
+ */
1143
+ function createRef() {
1144
+ return createShallowReadonlyProxy({ value: null });
1145
+ }
1146
+ function applyRefs(ref, value, refEffects) {
1147
+ if (!ref) return;
1148
+ const refs = toRefs(ref);
1149
+ const length = refs.length;
1150
+ for (let i = 0; i < length; i++) bindRefs(refs[i], value, refEffects);
1151
+ }
1152
+ function updateRefs(ref, value, refEffects) {
1153
+ if (!ref) {
1154
+ refEffects.forEach((fn, oldRef) => {
1155
+ refEffects.delete(oldRef);
1156
+ if (typeof fn === "function") fn();
1157
+ });
1158
+ return;
1159
+ }
1160
+ const newRefs = toRefs(ref);
1161
+ refEffects.forEach((fn, oldRef) => {
1162
+ if (newRefs.includes(oldRef)) return;
1163
+ refEffects.delete(oldRef);
1164
+ if (typeof fn === "function") fn();
1165
+ });
1166
+ const len = newRefs.length;
1167
+ for (let i = 0; i < len; i++) {
1168
+ const newRef = newRefs[i];
1169
+ if (refEffects.has(newRef)) continue;
1170
+ bindRefs(newRef, value, refEffects);
1171
+ }
1172
+ }
1173
+ function toRefs(ref) {
1174
+ return Array.isArray(ref) ? ref : [ref];
1175
+ }
1176
+ function bindRefs(ref, value, refEffects) {
1177
+ const type = typeof ref;
1178
+ if (type === "function") {
1179
+ const fn = ref(value);
1180
+ refEffects.set(ref, fn);
1181
+ } else if (type === "object") {
1182
+ internalWrite(() => {
1183
+ ref.value = value;
1184
+ });
1185
+ refEffects.set(ref, () => {
1186
+ internalWrite(() => {
1187
+ ref.value = null;
1188
+ });
1189
+ });
1190
+ } else throw refErrorFn("ref must be a function or `Ref<T>` object!");
1191
+ }
1192
+ //#endregion
1094
1193
  //#region src/base/component.ts
1095
1194
  var componentSetupStack = [];
1096
1195
  var componentErrorFn = makeError("component");
@@ -1099,14 +1198,6 @@ function getSetupContext(need = true) {
1099
1198
  if (!current && need) throw componentErrorFn("cannot be called outside the component!");
1100
1199
  return current;
1101
1200
  }
1102
- function toRefs(ref) {
1103
- return (Array.isArray(ref) ? ref : [ref]).filter((i) => {
1104
- return i instanceof DynamicRef;
1105
- });
1106
- }
1107
- function createReadonlyProxy(value) {
1108
- return new Proxy(value, readonlyProxyHandler);
1109
- }
1110
1201
  /**
1111
1202
  * Viewfly 组件管理类,用于管理组件的生命周期,上下文等
1112
1203
  */
@@ -1132,9 +1223,9 @@ var Component = class {
1132
1223
  this._dirty = true;
1133
1224
  this._changed = false;
1134
1225
  this.isFirstRendering = true;
1135
- this.refs = null;
1136
1226
  this.rawProps = props;
1137
- this.props = createReadonlyProxy({ ...props });
1227
+ this.props = createShallowReadonlyProxy({ ...props });
1228
+ this.refEffects = /* @__PURE__ */ new Map();
1138
1229
  this.listener = new Dep(() => {
1139
1230
  this.markAsDirtied();
1140
1231
  });
@@ -1154,20 +1245,14 @@ var Component = class {
1154
1245
  const render = this.type(this.props);
1155
1246
  const isRenderFn = typeof render === "function";
1156
1247
  this.instance = isRenderFn ? { $render: render } : render;
1157
- const refs = toRefs(this.props.ref);
1158
- if (refs.length) {
1159
- this.refs = refs;
1160
- onMounted(() => {
1161
- const refs = this.refs;
1162
- const length = refs.length;
1163
- for (let i = 0; i < length; i++) refs[i].bind(this.instance);
1164
- return () => {
1165
- const refs = this.refs;
1166
- const length = refs.length;
1167
- for (let i = 0; i < length; i++) refs[i].unBind(this.instance);
1168
- };
1169
- });
1170
- }
1248
+ onMounted(() => {
1249
+ applyRefs(this.props.ref, this.instance, this.refEffects);
1250
+ return () => {
1251
+ this.refEffects.forEach((fn) => {
1252
+ if (typeof fn === "function") fn();
1253
+ });
1254
+ };
1255
+ });
1171
1256
  componentSetupStack.pop();
1172
1257
  pushDepContext(this.listener);
1173
1258
  const template = this.instance.$render();
@@ -1178,7 +1263,7 @@ var Component = class {
1178
1263
  updateProps(newProps) {
1179
1264
  const oldProps = this.rawProps;
1180
1265
  this.rawProps = newProps;
1181
- const newRefs = toRefs(newProps.ref);
1266
+ const newRefs = newProps.ref;
1182
1267
  comparePropsWithCallbacks(oldProps, newProps, (key) => {
1183
1268
  internalWrite(() => {
1184
1269
  Reflect.deleteProperty(oldProps, key);
@@ -1192,22 +1277,7 @@ var Component = class {
1192
1277
  this.props[key] = value;
1193
1278
  });
1194
1279
  });
1195
- if (this.refs) {
1196
- const len = this.refs.length;
1197
- for (let i = 0; i < len; i++) {
1198
- const oldRef = this.refs[i];
1199
- if (!newRefs.includes(oldRef)) oldRef.unBind(this.instance);
1200
- }
1201
- }
1202
- const len = newRefs.length;
1203
- for (let i = 0; i < len; i++) newRefs[i].bind(this.instance);
1204
- if (len) this.refs = newRefs;
1205
- }
1206
- canUpdate(oldProps, newProps) {
1207
- if (typeof this.instance.$useMemo === "function") {
1208
- if (this.instance.$useMemo(newProps, oldProps)) return false;
1209
- }
1210
- return true;
1280
+ updateRefs(newRefs, this.instance, this.refEffects);
1211
1281
  }
1212
1282
  rerender() {
1213
1283
  this.listener.destroy();
@@ -1269,10 +1339,24 @@ var Component = class {
1269
1339
  };
1270
1340
  /**
1271
1341
  * 获取当前组件实例
1342
+ * @returns 当前组件实例
1343
+ * @example
1344
+ * ```tsx
1345
+ * function App() {
1346
+ * const instance = getCurrentInstance()
1347
+ * console.log(instance)
1348
+ * return () => <div>...</div>
1349
+ * }
1350
+ * ```
1272
1351
  */
1273
1352
  function getCurrentInstance() {
1274
1353
  return getSetupContext();
1275
1354
  }
1355
+ /**
1356
+ * 注册组件销毁回调函数
1357
+ * @param fn 要注册的回调函数
1358
+ * @internal
1359
+ */
1276
1360
  function registryComponentDestroyCallback(fn) {
1277
1361
  const component = getSetupContext(false);
1278
1362
  if (component) {
@@ -1376,24 +1460,22 @@ function Portal(props) {
1376
1460
  };
1377
1461
  }
1378
1462
  //#endregion
1379
- //#region src/reactive/watch.ts
1380
- function watch(trigger, callback) {
1381
- let prevFn;
1382
- const dep = new Dep(() => {
1463
+ //#region src/reactive/watch-effect.ts
1464
+ /**
1465
+ * 创建一个 watchEffect,立即执行 effect 函数,当依赖的值发生变化时,会再次执行 effect 函数。
1466
+ * watchEffect 会返回一个函数,用于停止监听
1467
+ * @param effect 执行的函数
1468
+ * @returns 一个函数,用于停止监听
1469
+ */
1470
+ function watchEffect(effect) {
1471
+ const dep = new Dep(function() {
1383
1472
  pushDepContext(dep);
1384
- const newValue = trigger();
1473
+ effect();
1385
1474
  popDepContext();
1386
- if (newValue === oldValue) return;
1387
- if (prevFn) prevFn();
1388
- prevFn = callback(newValue, oldValue);
1389
- oldValue = newValue;
1390
1475
  });
1391
1476
  pushDepContext(dep);
1392
- let oldValue = trigger();
1477
+ effect();
1393
1478
  popDepContext();
1394
- dep.destroyCallbacks.push(() => {
1395
- prevFn?.();
1396
- });
1397
1479
  function unWatch() {
1398
1480
  dep.destroy();
1399
1481
  }
@@ -1401,6 +1483,32 @@ function watch(trigger, callback) {
1401
1483
  return unWatch;
1402
1484
  }
1403
1485
  //#endregion
1486
+ //#region src/reactive/watch.ts
1487
+ /**
1488
+ * 创建一个 watch,当依赖的值发生变化时,会执行 callback 函数。
1489
+ * watch 会返回一个函数,用于停止监听。
1490
+ * @param trigger 触发函数,用于获取依赖的值
1491
+ * @param callback 回调函数,当依赖的值发生变化时,会执行 callback 函数
1492
+ * @returns 一个函数,用于停止监听
1493
+ */
1494
+ function watch(trigger, callback) {
1495
+ const initValue = {};
1496
+ let oldValue = initValue;
1497
+ const unWatch = watchEffect(function() {
1498
+ if (oldValue === initValue) {
1499
+ oldValue = trigger();
1500
+ return;
1501
+ }
1502
+ const newValue = trigger();
1503
+ if (newValue !== oldValue) {
1504
+ callback(newValue, oldValue);
1505
+ oldValue = newValue;
1506
+ }
1507
+ });
1508
+ registryComponentDestroyCallback(unWatch);
1509
+ return unWatch;
1510
+ }
1511
+ //#endregion
1404
1512
  //#region src/base/context.ts
1405
1513
  var injectMap = /* @__PURE__ */ new WeakMap();
1406
1514
  function getInjector(start) {
@@ -1411,6 +1519,36 @@ function getInjector(start) {
1411
1519
  }
1412
1520
  return new NullInjector();
1413
1521
  }
1522
+ /**
1523
+ * 创建一个上下文,用于在组件之间共享数据
1524
+ * @param providers 提供者,用于提供数据
1525
+ * @param scope 作用域,用于限制提供者的作用域
1526
+ * @param parentInjector 父注入器,用于自定义父注入器,默认从当前组件树中自动获取
1527
+ * @returns 一个上下文组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
1528
+ * @example
1529
+ * ```tsx
1530
+ * @Injectable()
1531
+ * class ExampleService {}
1532
+ *
1533
+ * function Child(props) {
1534
+ * const exampleService = inject(ExampleService)
1535
+ * console.log(exampleService)
1536
+ * return () => {
1537
+ * return <div>{props.children}</div>
1538
+ * }
1539
+ * }
1540
+ * function App() {
1541
+ * const Context = createContext([
1542
+ * ExampleService
1543
+ * ])
1544
+ * return () => {
1545
+ * return <Context>
1546
+ * <Child>test</Child>
1547
+ * </Context>
1548
+ * }
1549
+ * }
1550
+ * ```
1551
+ */
1414
1552
  function createContext(providers, scope, parentInjector) {
1415
1553
  return function context(props) {
1416
1554
  const instance = getCurrentInstance();
@@ -1421,6 +1559,33 @@ function createContext(providers, scope, parentInjector) {
1421
1559
  };
1422
1560
  };
1423
1561
  }
1562
+ /**
1563
+ * 创建一个上下文提供者组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
1564
+ * @param params 提供者参数
1565
+ * @returns 一个上下文提供者组件,组件的子元素都可以通过 inject 获取到提供者提供的数据
1566
+ * @example
1567
+ * ```tsx
1568
+ * const ExampleService = createContextProvider({
1569
+ * provide: ExampleService
1570
+ * })
1571
+ *
1572
+ * function Child() {
1573
+ * const exampleService = inject(ExampleService)
1574
+ * console.log(exampleService)
1575
+ * return () => {
1576
+ * return <div>{exampleService.name}</div>
1577
+ * }
1578
+ * }
1579
+ *
1580
+ * function App() {
1581
+ * const value = new ExampleService()
1582
+ * return () => {
1583
+ * return <ExampleService useValue={value}>
1584
+ * <Child/>
1585
+ * </ExampleService>
1586
+ * }
1587
+ * }
1588
+ */
1424
1589
  function createContextProvider(params) {
1425
1590
  return function contextProvider(props) {
1426
1591
  let Context = createContext([{
@@ -1442,6 +1607,19 @@ function createContextProvider(params) {
1442
1607
  }
1443
1608
  /**
1444
1609
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
1610
+ * @param token 注入的 token
1611
+ * @param notFoundValue 未找到时的值
1612
+ * @param flags 注入标志
1613
+ * @returns 注入的值
1614
+ * @example
1615
+ * ```tsx
1616
+ * function ChildComponent() {
1617
+ * const exampleService = inject(ExampleService)
1618
+ * console.log(exampleService)
1619
+ * return () => {
1620
+ * return <div>{exampleService.name}</div>
1621
+ * }
1622
+ * }
1445
1623
  */
1446
1624
  function inject(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
1447
1625
  return getInjector(getCurrentInstance()).get(token, notFoundValue, flags);
@@ -1482,21 +1660,9 @@ function withAnnotation(annotation, componentSetup) {
1482
1660
  //#region src/base/injection-tokens.ts
1483
1661
  var NativeRenderer = class {};
1484
1662
  //#endregion
1485
- //#region src/base/memo.ts
1486
- /**
1487
- * @deprecated 即将弃用,Viewfly 默认就有 memo 的效果
1488
- * @param canUseMemo
1489
- * @param render
1490
- */
1491
- function withMemo(canUseMemo, render) {
1492
- return {
1493
- $useMemo: canUseMemo,
1494
- $render: render
1495
- };
1496
- }
1497
- //#endregion
1498
1663
  //#region src/base/renderer.ts
1499
1664
  var listenerReg = /^on[A-Z]/;
1665
+ var nativeNodeRefRecord = /* @__PURE__ */ new Map();
1500
1666
  function createRenderer(component, nativeRenderer, namespace) {
1501
1667
  let isInit = true;
1502
1668
  return function render(host) {
@@ -1541,21 +1707,19 @@ function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, contex
1541
1707
  }
1542
1708
  function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1543
1709
  if (component.dirty) {
1544
- if (component.canUpdate(component.props, component.props)) {
1545
- const { atom, host, isParent, rootHost } = component.viewMetadata;
1546
- const context = {
1547
- host,
1548
- isParent,
1549
- rootHost
1550
- };
1551
- const diffAtom = atom.child;
1552
- patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
1553
- const next = atom.sibling;
1554
- if (next && next.jsxNode instanceof Component) {
1555
- const view = next.jsxNode.viewMetadata;
1556
- view.host = context.host;
1557
- view.isParent = context.isParent;
1558
- }
1710
+ const { atom, host, isParent, rootHost } = component.viewMetadata;
1711
+ const context = {
1712
+ host,
1713
+ isParent,
1714
+ rootHost
1715
+ };
1716
+ const diffAtom = atom.child;
1717
+ patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
1718
+ const next = atom.sibling;
1719
+ if (next && next.jsxNode instanceof Component) {
1720
+ const view = next.jsxNode.viewMetadata;
1721
+ view.host = context.host;
1722
+ view.isParent = context.isParent;
1559
1723
  }
1560
1724
  component.rendered();
1561
1725
  } else if (component.changed) {
@@ -1662,10 +1826,9 @@ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, old
1662
1826
  const newProps = newAtom.jsxNode.props;
1663
1827
  newAtom.jsxNode = component;
1664
1828
  needMove = needMove || newAtom.index - offset !== oldAtom.index;
1665
- const canUpdate = component.canUpdate(component.props, newProps);
1666
1829
  const propsIsChanged = hasChange(newProps, component.props);
1667
1830
  if (propsIsChanged) component.updateProps(newProps);
1668
- if (canUpdate && (propsIsChanged || component.dirty)) {
1831
+ if (propsIsChanged || component.dirty) {
1669
1832
  patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
1670
1833
  const next = oldAtom.sibling;
1671
1834
  if (next && next.jsxNode instanceof Component) {
@@ -1675,7 +1838,7 @@ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, old
1675
1838
  }
1676
1839
  } else {
1677
1840
  newAtom.child = oldAtom.child;
1678
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate || !component.changedSubComponents.size);
1841
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !component.changedSubComponents.size);
1679
1842
  }
1680
1843
  component.rendered();
1681
1844
  }
@@ -1726,8 +1889,10 @@ function cleanView(nativeRenderer, atom, needClean) {
1726
1889
  needClean = false;
1727
1890
  }
1728
1891
  if (atom.type === ElementAtomType) {
1729
- const ref = atom.jsxNode.props["ref"];
1730
- applyRefs(ref, atom.nativeNode, false);
1892
+ const record = nativeNodeRefRecord.get(atom);
1893
+ if (record) record.forEach((fn) => {
1894
+ if (typeof fn === "function") fn();
1895
+ });
1731
1896
  }
1732
1897
  cleanChildren(atom, nativeRenderer, needClean);
1733
1898
  }
@@ -1851,7 +2016,9 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
1851
2016
  });
1852
2017
  context.host = nativeNode;
1853
2018
  context.isParent = false;
1854
- applyRefs(bindingRefs, nativeNode, true);
2019
+ const refEffects = /* @__PURE__ */ new Map();
2020
+ nativeNodeRefRecord.set(atom, refEffects);
2021
+ applyRefs(bindingRefs, nativeNode, refEffects);
1855
2022
  }
1856
2023
  function createTextNode(nativeRenderer, atom, context) {
1857
2024
  const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
@@ -1870,7 +2037,6 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1870
2037
  reuseElementChildrenView(nativeRenderer, newAtom, context);
1871
2038
  return;
1872
2039
  }
1873
- let unBindRefs;
1874
2040
  let bindRefs;
1875
2041
  let updatedChildren = false;
1876
2042
  comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
@@ -1891,10 +2057,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1891
2057
  if (typeof oldValue === "function") nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1892
2058
  return;
1893
2059
  }
1894
- if (key === "ref") {
1895
- unBindRefs = oldValue;
1896
- return;
1897
- }
2060
+ if (key === "ref") return;
1898
2061
  nativeRenderer.removeProperty(nativeNode, key, isSvg);
1899
2062
  }, (key, value) => {
1900
2063
  if (key === "children") {
@@ -1952,26 +2115,17 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1952
2115
  return;
1953
2116
  }
1954
2117
  if (key === "ref") {
1955
- unBindRefs = oldValue;
1956
2118
  bindRefs = newValue;
1957
2119
  return;
1958
2120
  }
1959
2121
  nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
1960
2122
  });
1961
2123
  if (!updatedChildren) newAtom.child = oldAtom.child;
1962
- applyRefs(unBindRefs, nativeNode, false);
1963
- applyRefs(bindRefs, nativeNode, true);
1964
- }
1965
- function applyRefs(refs, nativeNode, binding) {
1966
- if (refs) {
1967
- const refList = Array.isArray(refs) ? refs : [refs];
1968
- const len = refList.length;
1969
- for (let i = 0; i < len; i++) {
1970
- const item = refList[i];
1971
- if (item instanceof DynamicRef) if (binding) item.bind(nativeNode);
1972
- else item.unBind(nativeNode);
1973
- }
1974
- }
2124
+ let refEffects = nativeNodeRefRecord.get(oldAtom);
2125
+ if (!refEffects) refEffects = /* @__PURE__ */ new Map();
2126
+ nativeNodeRefRecord.delete(oldAtom);
2127
+ nativeNodeRefRecord.set(newAtom, refEffects);
2128
+ updateRefs(bindRefs, nativeNode, refEffects);
1975
2129
  }
1976
2130
  //#endregion
1977
2131
  //#region src/base/root.component.ts
@@ -2055,39 +2209,16 @@ function viewfly(config) {
2055
2209
  }
2056
2210
  //#endregion
2057
2211
  //#region src/reactive/computed.ts
2058
- function computed(callback, isContinue) {
2059
- let isStop = false;
2060
- const dep = new Dep(() => {
2061
- if (isStop) return;
2062
- isStop = true;
2063
- dep.destroy();
2064
- pushDepContext(dep);
2065
- const value = callback();
2066
- popDepContext();
2067
- internalWrite(() => {
2068
- proxy.value = value;
2069
- });
2070
- canListen(value);
2071
- isStop = false;
2072
- });
2073
- pushDepContext(dep);
2074
- const value = callback();
2075
- popDepContext();
2076
- const proxy = new Proxy({ value }, readonlyProxyHandler);
2077
- function canListen(value) {
2078
- if (isContinue) {
2079
- if (isContinue(value) === false) {
2080
- dep.destroy();
2081
- return false;
2082
- }
2083
- }
2084
- return true;
2085
- }
2086
- if (!canListen(value)) return proxy;
2087
- registryComponentDestroyCallback(() => {
2088
- dep.destroy();
2089
- });
2090
- return proxy;
2212
+ /**
2213
+ * 创建一个 computed,当依赖的值发生变化时,会重新计算值。
2214
+ * computed 会返回一个对象,对象的 value 属性是计算的值。
2215
+ * @param getter 计算函数,用于计算值
2216
+ * @returns 一个对象,对象的 value 属性是计算的值
2217
+ */
2218
+ function computed(getter) {
2219
+ return { get value() {
2220
+ return getter();
2221
+ } };
2091
2222
  }
2092
2223
  //#endregion
2093
2224
  //#region src/reactive/shallow-reactive.ts
@@ -2133,7 +2264,7 @@ function shallowReactive(raw) {
2133
2264
  return proxy;
2134
2265
  }
2135
2266
  //#endregion
2136
- //#region src/signals/signal.ts
2267
+ //#region src/reactive/signal.ts
2137
2268
  /**
2138
2269
  * 组件状态管理器
2139
2270
  * @param state 初始状态
@@ -2158,86 +2289,14 @@ function shallowReactive(raw) {
2158
2289
  * }
2159
2290
  */
2160
2291
  function createSignal(state) {
2161
- const subscribers = /* @__PURE__ */ new Set();
2292
+ const ref = shallowReactive({ value: state });
2162
2293
  function signal() {
2163
- const listener = getDepContext();
2164
- if (listener && !subscribers.has(listener)) {
2165
- listener.destroyCallbacks.push(() => {
2166
- subscribers.delete(listener);
2167
- });
2168
- subscribers.add(listener);
2169
- }
2170
- return state;
2294
+ return ref.value;
2171
2295
  }
2172
2296
  signal.set = function(newValue) {
2173
- if (newValue === state) return;
2174
- state = newValue;
2175
- Array.from(subscribers).forEach((listener) => listener.effect());
2297
+ ref.value = newValue;
2176
2298
  };
2177
2299
  return signal;
2178
2300
  }
2179
2301
  //#endregion
2180
- //#region src/signals/derived.ts
2181
- /**
2182
- * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
2183
- * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
2184
- *
2185
- * @param fn
2186
- * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
2187
- */
2188
- function createDerived(fn, isContinue) {
2189
- let isStop = false;
2190
- function canListen(value) {
2191
- if (isContinue) {
2192
- if (isContinue(value) === false) {
2193
- listener.destroy();
2194
- return false;
2195
- }
2196
- }
2197
- return true;
2198
- }
2199
- const listener = new Dep(() => {
2200
- if (isStop) return;
2201
- isStop = true;
2202
- listener.destroy();
2203
- pushDepContext(listener);
2204
- const value = fn();
2205
- popDepContext();
2206
- signal.set(value);
2207
- canListen(value);
2208
- isStop = false;
2209
- });
2210
- pushDepContext(listener);
2211
- const value = fn();
2212
- const signal = createSignal(value);
2213
- popDepContext();
2214
- isStop = false;
2215
- if (canListen(value)) registryComponentDestroyCallback(() => listener.destroy());
2216
- return signal;
2217
- }
2218
- //#endregion
2219
- //#region src/signals/effect.ts
2220
- function createEffect(deps, callback) {
2221
- let prevFn;
2222
- const isArray = Array.isArray(deps);
2223
- const effect = new Dep(function() {
2224
- if (prevFn) prevFn();
2225
- const newValue = isArray ? deps.map((fn) => fn()) : deps();
2226
- prevFn = callback(newValue, oldValue);
2227
- oldValue = newValue;
2228
- });
2229
- pushDepContext(effect);
2230
- let oldValue = isArray ? deps.map((fn) => fn()) : deps();
2231
- popDepContext();
2232
- let isUnWatch = false;
2233
- function unWatch() {
2234
- if (isUnWatch) return;
2235
- isUnWatch = true;
2236
- if (prevFn) prevFn();
2237
- effect.destroy();
2238
- }
2239
- registryComponentDestroyCallback(unWatch);
2240
- return unWatch;
2241
- }
2242
- //#endregion
2243
- export { ArrayReactiveHandler, Component, Dep, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDerived, createDynamicRef, createEffect, createRef, createRenderer, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowReactive, toRaw, track, trigger, viewfly, watch, withAnnotation, withMark, withMemo };
2302
+ export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };