@viewfly/core 2.0.0-alpha.3 → 2.0.0-alpha.5

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.
@@ -436,6 +436,7 @@ declare class Component {
436
436
  * 获取当前组件实例
437
437
  */
438
438
  declare function getCurrentInstance(): Component;
439
+ declare function registryComponentDestroyCallback(fn: () => void): void;
439
440
 
440
441
  declare function createContext(providers: Provider[], scope?: Scope | null, parentInjector?: Injector): (props: Props) => () => JSXNode | JSXNode[];
441
442
  /**
@@ -467,6 +468,16 @@ interface ComponentAnnotation {
467
468
  */
468
469
  declare function withAnnotation<T extends ComponentSetup>(annotation: ComponentAnnotation, componentSetup: T): T;
469
470
 
471
+ declare class Dep {
472
+ effect: () => void;
473
+ destroyCallbacks: Array<() => void>;
474
+ constructor(effect: () => void);
475
+ destroy(): void;
476
+ }
477
+ declare function getDepContext(): Dep | undefined;
478
+ declare function pushDepContext(dep: Dep): void;
479
+ declare function popDepContext(): void;
480
+
470
481
  declare function withMemo<T extends Props = Props>(canUseMemo: ComponentInstance<T>['$useMemo'], render: () => JSXNode): ComponentInstance<T>;
471
482
 
472
483
  declare const ElementNamespaceMap: {
@@ -518,15 +529,6 @@ interface Computed<T> {
518
529
  }
519
530
  declare function computed<T>(callback: () => T, isContinue?: (data: T) => unknown): Computed<T>;
520
531
 
521
- declare class Dep {
522
- effect: () => void;
523
- destroyCallbacks: Array<() => void>;
524
- constructor(effect: () => void);
525
- destroy(): void;
526
- }
527
- declare function getDepContext(): Dep | undefined;
528
- declare function pushDepContext(dep: Dep): void;
529
- declare function popDepContext(): void;
530
532
  declare enum TrackOpTypes {
531
533
  Get = "Get",
532
534
  Has = "Has",
@@ -540,7 +542,6 @@ declare enum TriggerOpTypes {
540
542
  }
541
543
  declare function track(target: object, type: TrackOpTypes, key?: unknown): void;
542
544
  declare function trigger(target: object, type: TriggerOpTypes, key?: unknown): void;
543
- declare function registryComponentDestroyCallback(fn: () => void): void;
544
545
 
545
546
  declare const rawToProxyCache: WeakMap<object, any>;
546
547
  declare const proxyToRawCache: WeakMap<object, any>;
@@ -640,4 +641,74 @@ declare function shallowReactive<T>(raw: T): T;
640
641
 
641
642
  declare function watch<T>(trigger: () => T, callback: (newValue: T, oldValue: T) => (() => any) | void): () => void;
642
643
 
643
- export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, ArrayReactiveHandler, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentViewMetadata, type Computed, type Config, type ConstructorProvider, Dep, DynamicRef, type ElementNamespace, ElementNamespaceMap, type ExistingProvider, type ExtractInstanceType, type ExtractValueType, type FactoryProvider, ForwardRef, Fragment, Inject, type InjectDecorator, InjectFlags, Injectable, type InjectableDecorator, type InjectableOptions, InjectionToken, Injector, JSX, type JSXNode, JSXNodeFactory, type Key, type LifeCycleCallback, MapReactiveHandler, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, ObjectReactiveHandler, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type ProvideScope, type Provider, type ReactiveConfig, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, SetReactiveHandler, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, comparePropsWithCallbacks, computed, createContext, createDynamicRef, createRef, createRenderer, 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, withMemo };
644
+ /**
645
+ * 组件状态实例,直接调用可以获取最新的状态,通过 set 方法可以更新状态
646
+ */
647
+ interface Signal<T> {
648
+ /**
649
+ * 直接调用一个 Signal 实例,可以获取最新状态
650
+ */
651
+ (): T;
652
+ /**
653
+ * 更新组件状态的方法,可以传入最新的值
654
+ * @param newState
655
+ */
656
+ set(newState: T): void;
657
+ }
658
+ /**
659
+ * 组件状态管理器
660
+ * @param state 初始状态
661
+ * @example
662
+ * ```tsx
663
+ * function App() {
664
+ * // 初始化状态
665
+ * const state = createSignal(1)
666
+ *
667
+ * return () => {
668
+ * <div>
669
+ * <div>当前值为:{state()}</div>
670
+ * <div>
671
+ * <button type="button" onClick={() => {
672
+ * // 当点击时更新状态
673
+ * state.set(state() + 1)
674
+ * }
675
+ * }>updateState</button>
676
+ * </div>
677
+ * </div>
678
+ * }
679
+ * }
680
+ */
681
+ declare function createSignal<T>(state: T): Signal<T>;
682
+
683
+ /**
684
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
685
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
686
+ *
687
+ * @param fn
688
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
689
+ */
690
+ declare function createDerived<T>(fn: () => T, isContinue?: (data: T) => unknown): Signal<T>;
691
+
692
+ interface EffectCallback<T> {
693
+ (newValue: T, oldValue: T): void | (() => void);
694
+ }
695
+ /**
696
+ * 监听状态变化,当任意一个状态发生变更时,触发回调。
697
+ * createEffect 会返回一个取消监听的函数,调用此函数,可以取消监听。
698
+ * 当在组件中调用时,组件销毁时会自动取消监听。
699
+ * @param deps 依赖的状态 Signal,可以是一个 Signal,只可以一个数包含 Signal 的数组,或者是一个求值函数
700
+ * @param callback 状态变更后的回调函数
701
+ */
702
+ declare function createEffect<T>(deps: Signal<T>, callback: EffectCallback<T>): () => void;
703
+ declare function createEffect<T>(deps: [Signal<T>], callback: EffectCallback<[T]>): () => void;
704
+ declare function createEffect<T, T1>(deps: [Signal<T>, Signal<T1>], callback: EffectCallback<[T, T1]>): () => void;
705
+ declare function createEffect<T, T1, T2>(deps: [Signal<T>, Signal<T1>, Signal<T2>], callback: EffectCallback<[T, T1, T2]>): () => void;
706
+ declare function createEffect<T, T1, T2, T3>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>], callback: EffectCallback<[T, T1, T2, T3]>): () => void;
707
+ declare function createEffect<T, T1, T2, T3, T4>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>], callback: EffectCallback<[T, T1, T2, T3, T4]>): () => void;
708
+ declare function createEffect<T, T1, T2, T3, T4, T5>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>], callback: EffectCallback<[T, T1, T2, T3, T4, T5]>): () => void;
709
+ declare function createEffect<T, T1, T2, T3, T4, T5, T6>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>, Signal<T6>], callback: EffectCallback<[T, T1, T2, T3, T4, T5, T6]>): () => void;
710
+ declare function createEffect<T, T1, T2, T3, T4, T5, T6, T7>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>, Signal<T6>, Signal<T7>], callback: EffectCallback<[T, T1, T2, T3, T4, T5, T6, T7]>): () => void;
711
+ declare function createEffect<T>(deps: () => T, callback: EffectCallback<T>): () => void;
712
+ declare function createEffect<T = any>(deps: Signal<any>[], callback: EffectCallback<T[]>): () => void;
713
+
714
+ export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, ArrayReactiveHandler, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentViewMetadata, type Computed, type Config, type ConstructorProvider, Dep, DynamicRef, type EffectCallback, type ElementNamespace, ElementNamespaceMap, type ExistingProvider, type ExtractInstanceType, type ExtractValueType, type FactoryProvider, ForwardRef, Fragment, Inject, type InjectDecorator, InjectFlags, Injectable, type InjectableDecorator, type InjectableOptions, InjectionToken, Injector, JSX, type JSXNode, JSXNodeFactory, type Key, type LifeCycleCallback, MapReactiveHandler, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, ObjectReactiveHandler, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type ProvideScope, type Provider, type ReactiveConfig, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, SetReactiveHandler, type Signal, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, comparePropsWithCallbacks, computed, createContext, 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, withMemo };
@@ -800,6 +800,7 @@ function pushDepContext(dep) {
800
800
  function popDepContext() {
801
801
  deps.pop();
802
802
  }
803
+
803
804
  const subscribers = new WeakMap();
804
805
  function getSubscriber(target) {
805
806
  let subscriber = subscribers.get(target);
@@ -883,15 +884,6 @@ function trigger(target, type, key = unKnownKey) {
883
884
  }
884
885
  }
885
886
  }
886
- function registryComponentDestroyCallback(fn) {
887
- const component = getSetupContext(false);
888
- if (component) {
889
- if (!component.unmountedCallbacks) {
890
- component.unmountedCallbacks = [];
891
- }
892
- component.unmountedCallbacks.push(fn);
893
- }
894
- }
895
887
 
896
888
  function createIterableIterator(wrapper) {
897
889
  return {
@@ -1632,6 +1624,15 @@ class Component {
1632
1624
  function getCurrentInstance() {
1633
1625
  return getSetupContext();
1634
1626
  }
1627
+ function registryComponentDestroyCallback(fn) {
1628
+ const component = getSetupContext(false);
1629
+ if (component) {
1630
+ if (!component.unmountedCallbacks) {
1631
+ component.unmountedCallbacks = [];
1632
+ }
1633
+ component.unmountedCallbacks.push(fn);
1634
+ }
1635
+ }
1635
1636
 
1636
1637
  const injectMap = new WeakMap();
1637
1638
  function getInjector(start) {
@@ -1812,11 +1813,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1812
1813
  }
1813
1814
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1814
1815
  const commits = [];
1815
- function changeOffset() {
1816
- offset++;
1817
- }
1818
1816
  while (newAtom) {
1819
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1817
+ oldAtom = createChanges(newAtom, oldAtom, commits);
1820
1818
  newAtom = newAtom.sibling;
1821
1819
  }
1822
1820
  let dirtyDiffAtom = oldAtom;
@@ -1827,7 +1825,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1827
1825
  let offset = 0;
1828
1826
  const len = commits.length;
1829
1827
  for (let i = 0; i < len; i++) {
1830
- const commit = commits[i];
1831
1828
  while (oldAtom) {
1832
1829
  if (oldAtom.index <= i) {
1833
1830
  offset--;
@@ -1836,27 +1833,34 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1836
1833
  }
1837
1834
  break;
1838
1835
  }
1839
- commit.callback(commit.params, offset, needMove);
1836
+ const { dirtyAtom, newAtom } = commits[i];
1837
+ if (dirtyAtom) {
1838
+ switch (dirtyAtom.type) {
1839
+ case ElementAtomType:
1840
+ updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, dirtyAtom);
1841
+ break;
1842
+ case TextAtomType:
1843
+ updateText(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1844
+ break;
1845
+ case ComponentAtomType:
1846
+ updateComponent(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1847
+ break;
1848
+ }
1849
+ }
1850
+ else {
1851
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1852
+ offset++;
1853
+ }
1840
1854
  }
1841
1855
  }
1842
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1856
+ function createChanges(newAtom, oldAtom, commits) {
1843
1857
  const startDiffAtom = oldAtom;
1844
1858
  let prev = null;
1845
1859
  while (oldAtom) {
1846
- const newAtomType = newAtom.type;
1847
- if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1860
+ if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1848
1861
  commits.push({
1849
- callback: newAtomType === TextAtomType ? updateText :
1850
- newAtomType === ComponentAtomType ? updateComponent :
1851
- updateElement,
1852
- params: {
1853
- oldAtom,
1854
- newAtom,
1855
- nativeRenderer,
1856
- context,
1857
- effect,
1858
- parentComponent
1859
- }
1862
+ dirtyAtom: oldAtom,
1863
+ newAtom
1860
1864
  });
1861
1865
  const next = oldAtom.sibling;
1862
1866
  if (!prev) {
@@ -1869,25 +1873,12 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1869
1873
  oldAtom = oldAtom.sibling;
1870
1874
  }
1871
1875
  commits.push({
1872
- callback: patchUpdate,
1873
- params: {
1874
- oldAtom: oldAtom,
1875
- newAtom,
1876
- nativeRenderer,
1877
- context,
1878
- effect,
1879
- parentComponent
1880
- }
1876
+ dirtyAtom: null,
1877
+ newAtom
1881
1878
  });
1882
1879
  return startDiffAtom;
1883
1880
  }
1884
- function patchUpdate(params) {
1885
- const { nativeRenderer, parentComponent, newAtom, context, effect } = params;
1886
- buildView(nativeRenderer, parentComponent, newAtom, context);
1887
- effect();
1888
- }
1889
- function updateText(params, offset, needMove) {
1890
- const { oldAtom, newAtom, nativeRenderer, context } = params;
1881
+ function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1891
1882
  const nativeNode = oldAtom.nativeNode;
1892
1883
  newAtom.nativeNode = nativeNode;
1893
1884
  if (needMove || newAtom.index - offset !== oldAtom.index) {
@@ -1896,23 +1887,21 @@ function updateText(params, offset, needMove) {
1896
1887
  context.host = nativeNode;
1897
1888
  context.isParent = false;
1898
1889
  }
1899
- function updateElement(params, offset, needMove) {
1900
- const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1901
- newAtom.nativeNode = oldAtom.nativeNode;
1890
+ function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
1891
+ const nativeNode = oldAtom.nativeNode;
1892
+ newAtom.nativeNode = nativeNode;
1902
1893
  if (needMove || newAtom.index - offset !== oldAtom.index) {
1903
1894
  insertNode(nativeRenderer, newAtom, context);
1904
1895
  }
1905
- context.host = newAtom.nativeNode;
1896
+ context.host = nativeNode;
1906
1897
  context.isParent = false;
1907
1898
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1908
- host: newAtom.nativeNode,
1899
+ host: nativeNode,
1909
1900
  isParent: true,
1910
1901
  rootHost: context.rootHost
1911
1902
  });
1912
1903
  }
1913
- function updateComponent(params, offset, needMove) {
1914
- const { oldAtom, newAtom, nativeRenderer } = params;
1915
- let context = params.context;
1904
+ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1916
1905
  const component = oldAtom.jsxNode;
1917
1906
  const portalHost = component.instance.$portalHost;
1918
1907
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
@@ -1936,23 +1925,26 @@ function updateComponent(params, offset, needMove) {
1936
1925
  }
1937
1926
  else {
1938
1927
  newAtom.child = oldAtom.child;
1939
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove, true);
1928
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate || !component.changedSubComponents.size);
1940
1929
  }
1941
1930
  component.rendered();
1942
1931
  }
1943
1932
  function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
1944
1933
  const updateContext = (atom) => {
1945
- if (atom.jsxNode instanceof Component) {
1934
+ const jsxNode = atom.jsxNode;
1935
+ if (jsxNode instanceof Component) {
1946
1936
  reuseComponentView(nativeRenderer, atom.child, context, moveView, skipSubComponentDiff);
1947
1937
  if (!skipSubComponentDiff) {
1948
- deepUpdateByComponentDirtyTree(nativeRenderer, atom.jsxNode, moveView);
1938
+ deepUpdateByComponentDirtyTree(nativeRenderer, jsxNode, moveView);
1949
1939
  }
1950
1940
  }
1951
1941
  else {
1952
1942
  if (moveView) {
1953
1943
  insertNode(nativeRenderer, atom, context);
1954
1944
  }
1955
- reuseElementChildrenView(nativeRenderer, atom);
1945
+ if (!skipSubComponentDiff) {
1946
+ reuseElementChildrenView(nativeRenderer, atom);
1947
+ }
1956
1948
  context.isParent = false;
1957
1949
  context.host = atom.nativeNode;
1958
1950
  }
@@ -1962,7 +1954,7 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1962
1954
  child = child.sibling;
1963
1955
  }
1964
1956
  }
1965
- function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
1957
+ function reuseElementChildrenView(nativeRenderer, atom, context) {
1966
1958
  let child = atom.child;
1967
1959
  while (child) {
1968
1960
  if (child.jsxNode instanceof Component) {
@@ -2262,7 +2254,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2262
2254
  });
2263
2255
  if (!updatedChildren) {
2264
2256
  newAtom.child = oldAtom.child;
2265
- reuseElementChildrenView(nativeRenderer, newAtom);
2257
+ // reuseElementChildrenView(nativeRenderer, newAtom, context)
2266
2258
  }
2267
2259
  applyRefs(unBindRefs, nativeNode, false);
2268
2260
  applyRefs(bindRefs, nativeNode, true);
@@ -2507,4 +2499,123 @@ function watch(trigger, callback) {
2507
2499
  return unWatch;
2508
2500
  }
2509
2501
 
2510
- export { ArrayReactiveHandler, Component, Dep, DynamicRef, ElementNamespaceMap, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, comparePropsWithCallbacks, computed, createContext, createDynamicRef, createRef, createRenderer, 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, withMemo };
2502
+ /**
2503
+ * 组件状态管理器
2504
+ * @param state 初始状态
2505
+ * @example
2506
+ * ```tsx
2507
+ * function App() {
2508
+ * // 初始化状态
2509
+ * const state = createSignal(1)
2510
+ *
2511
+ * return () => {
2512
+ * <div>
2513
+ * <div>当前值为:{state()}</div>
2514
+ * <div>
2515
+ * <button type="button" onClick={() => {
2516
+ * // 当点击时更新状态
2517
+ * state.set(state() + 1)
2518
+ * }
2519
+ * }>updateState</button>
2520
+ * </div>
2521
+ * </div>
2522
+ * }
2523
+ * }
2524
+ */
2525
+ function createSignal(state) {
2526
+ const subscribers = new Set();
2527
+ function signal() {
2528
+ const listener = getDepContext();
2529
+ if (listener && !subscribers.has(listener)) {
2530
+ listener.destroyCallbacks.push(() => {
2531
+ subscribers.delete(listener);
2532
+ });
2533
+ subscribers.add(listener);
2534
+ }
2535
+ return state;
2536
+ }
2537
+ signal.set = function (newValue) {
2538
+ if (newValue === state) {
2539
+ return;
2540
+ }
2541
+ state = newValue;
2542
+ const listeners = Array.from(subscribers);
2543
+ listeners.forEach(listener => listener.effect());
2544
+ };
2545
+ return signal;
2546
+ }
2547
+
2548
+ /**
2549
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
2550
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
2551
+ *
2552
+ * @param fn
2553
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
2554
+ */
2555
+ function createDerived(fn, isContinue) {
2556
+ let isStop = false;
2557
+ function canListen(value) {
2558
+ if (isContinue) {
2559
+ const b = isContinue(value);
2560
+ if (b === false) {
2561
+ listener.destroy();
2562
+ return false;
2563
+ }
2564
+ }
2565
+ return true;
2566
+ }
2567
+ const listener = new Dep(() => {
2568
+ if (isStop) {
2569
+ return;
2570
+ }
2571
+ isStop = true;
2572
+ listener.destroy();
2573
+ pushDepContext(listener);
2574
+ const value = fn();
2575
+ popDepContext();
2576
+ signal.set(value);
2577
+ canListen(value);
2578
+ isStop = false;
2579
+ });
2580
+ pushDepContext(listener);
2581
+ const value = fn();
2582
+ const signal = createSignal(value);
2583
+ popDepContext();
2584
+ isStop = false;
2585
+ if (canListen(value)) {
2586
+ registryComponentDestroyCallback(() => listener.destroy());
2587
+ }
2588
+ return signal;
2589
+ }
2590
+
2591
+ /* eslint-enable max-len*/
2592
+ function createEffect(deps, callback) {
2593
+ let prevFn;
2594
+ const isArray = Array.isArray(deps);
2595
+ const effect = new Dep(function () {
2596
+ if (prevFn) {
2597
+ prevFn();
2598
+ }
2599
+ const newValue = isArray ? deps.map(fn => fn()) : deps();
2600
+ prevFn = callback(newValue, oldValue);
2601
+ oldValue = newValue;
2602
+ });
2603
+ pushDepContext(effect);
2604
+ let oldValue = isArray ? deps.map(fn => fn()) : deps();
2605
+ popDepContext();
2606
+ let isUnWatch = false;
2607
+ function unWatch() {
2608
+ if (isUnWatch) {
2609
+ return;
2610
+ }
2611
+ isUnWatch = true;
2612
+ if (prevFn) {
2613
+ prevFn();
2614
+ }
2615
+ effect.destroy();
2616
+ }
2617
+ registryComponentDestroyCallback(unWatch);
2618
+ return unWatch;
2619
+ }
2620
+
2621
+ export { ArrayReactiveHandler, Component, Dep, DynamicRef, ElementNamespaceMap, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, comparePropsWithCallbacks, computed, createContext, 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, withMemo };
package/bundles/index.js CHANGED
@@ -802,6 +802,7 @@ function pushDepContext(dep) {
802
802
  function popDepContext() {
803
803
  deps.pop();
804
804
  }
805
+
805
806
  const subscribers = new WeakMap();
806
807
  function getSubscriber(target) {
807
808
  let subscriber = subscribers.get(target);
@@ -885,15 +886,6 @@ function trigger(target, type, key = unKnownKey) {
885
886
  }
886
887
  }
887
888
  }
888
- function registryComponentDestroyCallback(fn) {
889
- const component = getSetupContext(false);
890
- if (component) {
891
- if (!component.unmountedCallbacks) {
892
- component.unmountedCallbacks = [];
893
- }
894
- component.unmountedCallbacks.push(fn);
895
- }
896
- }
897
889
 
898
890
  function createIterableIterator(wrapper) {
899
891
  return {
@@ -1634,6 +1626,15 @@ class Component {
1634
1626
  function getCurrentInstance() {
1635
1627
  return getSetupContext();
1636
1628
  }
1629
+ function registryComponentDestroyCallback(fn) {
1630
+ const component = getSetupContext(false);
1631
+ if (component) {
1632
+ if (!component.unmountedCallbacks) {
1633
+ component.unmountedCallbacks = [];
1634
+ }
1635
+ component.unmountedCallbacks.push(fn);
1636
+ }
1637
+ }
1637
1638
 
1638
1639
  const injectMap = new WeakMap();
1639
1640
  function getInjector(start) {
@@ -1814,11 +1815,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1814
1815
  }
1815
1816
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1816
1817
  const commits = [];
1817
- function changeOffset() {
1818
- offset++;
1819
- }
1820
1818
  while (newAtom) {
1821
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1819
+ oldAtom = createChanges(newAtom, oldAtom, commits);
1822
1820
  newAtom = newAtom.sibling;
1823
1821
  }
1824
1822
  let dirtyDiffAtom = oldAtom;
@@ -1829,7 +1827,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1829
1827
  let offset = 0;
1830
1828
  const len = commits.length;
1831
1829
  for (let i = 0; i < len; i++) {
1832
- const commit = commits[i];
1833
1830
  while (oldAtom) {
1834
1831
  if (oldAtom.index <= i) {
1835
1832
  offset--;
@@ -1838,27 +1835,34 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1838
1835
  }
1839
1836
  break;
1840
1837
  }
1841
- commit.callback(commit.params, offset, needMove);
1838
+ const { dirtyAtom, newAtom } = commits[i];
1839
+ if (dirtyAtom) {
1840
+ switch (dirtyAtom.type) {
1841
+ case ElementAtomType:
1842
+ updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, dirtyAtom);
1843
+ break;
1844
+ case TextAtomType:
1845
+ updateText(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1846
+ break;
1847
+ case ComponentAtomType:
1848
+ updateComponent(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1849
+ break;
1850
+ }
1851
+ }
1852
+ else {
1853
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1854
+ offset++;
1855
+ }
1842
1856
  }
1843
1857
  }
1844
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1858
+ function createChanges(newAtom, oldAtom, commits) {
1845
1859
  const startDiffAtom = oldAtom;
1846
1860
  let prev = null;
1847
1861
  while (oldAtom) {
1848
- const newAtomType = newAtom.type;
1849
- if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1862
+ if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1850
1863
  commits.push({
1851
- callback: newAtomType === TextAtomType ? updateText :
1852
- newAtomType === ComponentAtomType ? updateComponent :
1853
- updateElement,
1854
- params: {
1855
- oldAtom,
1856
- newAtom,
1857
- nativeRenderer,
1858
- context,
1859
- effect,
1860
- parentComponent
1861
- }
1864
+ dirtyAtom: oldAtom,
1865
+ newAtom
1862
1866
  });
1863
1867
  const next = oldAtom.sibling;
1864
1868
  if (!prev) {
@@ -1871,25 +1875,12 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1871
1875
  oldAtom = oldAtom.sibling;
1872
1876
  }
1873
1877
  commits.push({
1874
- callback: patchUpdate,
1875
- params: {
1876
- oldAtom: oldAtom,
1877
- newAtom,
1878
- nativeRenderer,
1879
- context,
1880
- effect,
1881
- parentComponent
1882
- }
1878
+ dirtyAtom: null,
1879
+ newAtom
1883
1880
  });
1884
1881
  return startDiffAtom;
1885
1882
  }
1886
- function patchUpdate(params) {
1887
- const { nativeRenderer, parentComponent, newAtom, context, effect } = params;
1888
- buildView(nativeRenderer, parentComponent, newAtom, context);
1889
- effect();
1890
- }
1891
- function updateText(params, offset, needMove) {
1892
- const { oldAtom, newAtom, nativeRenderer, context } = params;
1883
+ function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1893
1884
  const nativeNode = oldAtom.nativeNode;
1894
1885
  newAtom.nativeNode = nativeNode;
1895
1886
  if (needMove || newAtom.index - offset !== oldAtom.index) {
@@ -1898,23 +1889,21 @@ function updateText(params, offset, needMove) {
1898
1889
  context.host = nativeNode;
1899
1890
  context.isParent = false;
1900
1891
  }
1901
- function updateElement(params, offset, needMove) {
1902
- const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1903
- newAtom.nativeNode = oldAtom.nativeNode;
1892
+ function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
1893
+ const nativeNode = oldAtom.nativeNode;
1894
+ newAtom.nativeNode = nativeNode;
1904
1895
  if (needMove || newAtom.index - offset !== oldAtom.index) {
1905
1896
  insertNode(nativeRenderer, newAtom, context);
1906
1897
  }
1907
- context.host = newAtom.nativeNode;
1898
+ context.host = nativeNode;
1908
1899
  context.isParent = false;
1909
1900
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1910
- host: newAtom.nativeNode,
1901
+ host: nativeNode,
1911
1902
  isParent: true,
1912
1903
  rootHost: context.rootHost
1913
1904
  });
1914
1905
  }
1915
- function updateComponent(params, offset, needMove) {
1916
- const { oldAtom, newAtom, nativeRenderer } = params;
1917
- let context = params.context;
1906
+ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1918
1907
  const component = oldAtom.jsxNode;
1919
1908
  const portalHost = component.instance.$portalHost;
1920
1909
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
@@ -1938,23 +1927,26 @@ function updateComponent(params, offset, needMove) {
1938
1927
  }
1939
1928
  else {
1940
1929
  newAtom.child = oldAtom.child;
1941
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove, true);
1930
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate || !component.changedSubComponents.size);
1942
1931
  }
1943
1932
  component.rendered();
1944
1933
  }
1945
1934
  function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
1946
1935
  const updateContext = (atom) => {
1947
- if (atom.jsxNode instanceof Component) {
1936
+ const jsxNode = atom.jsxNode;
1937
+ if (jsxNode instanceof Component) {
1948
1938
  reuseComponentView(nativeRenderer, atom.child, context, moveView, skipSubComponentDiff);
1949
1939
  if (!skipSubComponentDiff) {
1950
- deepUpdateByComponentDirtyTree(nativeRenderer, atom.jsxNode, moveView);
1940
+ deepUpdateByComponentDirtyTree(nativeRenderer, jsxNode, moveView);
1951
1941
  }
1952
1942
  }
1953
1943
  else {
1954
1944
  if (moveView) {
1955
1945
  insertNode(nativeRenderer, atom, context);
1956
1946
  }
1957
- reuseElementChildrenView(nativeRenderer, atom);
1947
+ if (!skipSubComponentDiff) {
1948
+ reuseElementChildrenView(nativeRenderer, atom);
1949
+ }
1958
1950
  context.isParent = false;
1959
1951
  context.host = atom.nativeNode;
1960
1952
  }
@@ -1964,7 +1956,7 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1964
1956
  child = child.sibling;
1965
1957
  }
1966
1958
  }
1967
- function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
1959
+ function reuseElementChildrenView(nativeRenderer, atom, context) {
1968
1960
  let child = atom.child;
1969
1961
  while (child) {
1970
1962
  if (child.jsxNode instanceof Component) {
@@ -2264,7 +2256,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2264
2256
  });
2265
2257
  if (!updatedChildren) {
2266
2258
  newAtom.child = oldAtom.child;
2267
- reuseElementChildrenView(nativeRenderer, newAtom);
2259
+ // reuseElementChildrenView(nativeRenderer, newAtom, context)
2268
2260
  }
2269
2261
  applyRefs(unBindRefs, nativeNode, false);
2270
2262
  applyRefs(bindRefs, nativeNode, true);
@@ -2509,6 +2501,125 @@ function watch(trigger, callback) {
2509
2501
  return unWatch;
2510
2502
  }
2511
2503
 
2504
+ /**
2505
+ * 组件状态管理器
2506
+ * @param state 初始状态
2507
+ * @example
2508
+ * ```tsx
2509
+ * function App() {
2510
+ * // 初始化状态
2511
+ * const state = createSignal(1)
2512
+ *
2513
+ * return () => {
2514
+ * <div>
2515
+ * <div>当前值为:{state()}</div>
2516
+ * <div>
2517
+ * <button type="button" onClick={() => {
2518
+ * // 当点击时更新状态
2519
+ * state.set(state() + 1)
2520
+ * }
2521
+ * }>updateState</button>
2522
+ * </div>
2523
+ * </div>
2524
+ * }
2525
+ * }
2526
+ */
2527
+ function createSignal(state) {
2528
+ const subscribers = new Set();
2529
+ function signal() {
2530
+ const listener = getDepContext();
2531
+ if (listener && !subscribers.has(listener)) {
2532
+ listener.destroyCallbacks.push(() => {
2533
+ subscribers.delete(listener);
2534
+ });
2535
+ subscribers.add(listener);
2536
+ }
2537
+ return state;
2538
+ }
2539
+ signal.set = function (newValue) {
2540
+ if (newValue === state) {
2541
+ return;
2542
+ }
2543
+ state = newValue;
2544
+ const listeners = Array.from(subscribers);
2545
+ listeners.forEach(listener => listener.effect());
2546
+ };
2547
+ return signal;
2548
+ }
2549
+
2550
+ /**
2551
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
2552
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
2553
+ *
2554
+ * @param fn
2555
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
2556
+ */
2557
+ function createDerived(fn, isContinue) {
2558
+ let isStop = false;
2559
+ function canListen(value) {
2560
+ if (isContinue) {
2561
+ const b = isContinue(value);
2562
+ if (b === false) {
2563
+ listener.destroy();
2564
+ return false;
2565
+ }
2566
+ }
2567
+ return true;
2568
+ }
2569
+ const listener = new Dep(() => {
2570
+ if (isStop) {
2571
+ return;
2572
+ }
2573
+ isStop = true;
2574
+ listener.destroy();
2575
+ pushDepContext(listener);
2576
+ const value = fn();
2577
+ popDepContext();
2578
+ signal.set(value);
2579
+ canListen(value);
2580
+ isStop = false;
2581
+ });
2582
+ pushDepContext(listener);
2583
+ const value = fn();
2584
+ const signal = createSignal(value);
2585
+ popDepContext();
2586
+ isStop = false;
2587
+ if (canListen(value)) {
2588
+ registryComponentDestroyCallback(() => listener.destroy());
2589
+ }
2590
+ return signal;
2591
+ }
2592
+
2593
+ /* eslint-enable max-len*/
2594
+ function createEffect(deps, callback) {
2595
+ let prevFn;
2596
+ const isArray = Array.isArray(deps);
2597
+ const effect = new Dep(function () {
2598
+ if (prevFn) {
2599
+ prevFn();
2600
+ }
2601
+ const newValue = isArray ? deps.map(fn => fn()) : deps();
2602
+ prevFn = callback(newValue, oldValue);
2603
+ oldValue = newValue;
2604
+ });
2605
+ pushDepContext(effect);
2606
+ let oldValue = isArray ? deps.map(fn => fn()) : deps();
2607
+ popDepContext();
2608
+ let isUnWatch = false;
2609
+ function unWatch() {
2610
+ if (isUnWatch) {
2611
+ return;
2612
+ }
2613
+ isUnWatch = true;
2614
+ if (prevFn) {
2615
+ prevFn();
2616
+ }
2617
+ effect.destroy();
2618
+ }
2619
+ registryComponentDestroyCallback(unWatch);
2620
+ return unWatch;
2621
+ }
2622
+
2512
2623
  exports.ArrayReactiveHandler = ArrayReactiveHandler;
2513
2624
  exports.Component = Component;
2514
2625
  exports.Dep = Dep;
@@ -2539,9 +2650,12 @@ exports.Type = Type;
2539
2650
  exports.comparePropsWithCallbacks = comparePropsWithCallbacks;
2540
2651
  exports.computed = computed;
2541
2652
  exports.createContext = createContext;
2653
+ exports.createDerived = createDerived;
2542
2654
  exports.createDynamicRef = createDynamicRef;
2655
+ exports.createEffect = createEffect;
2543
2656
  exports.createRef = createRef;
2544
2657
  exports.createRenderer = createRenderer;
2658
+ exports.createSignal = createSignal;
2545
2659
  exports.defaultArrayReactiveHandler = defaultArrayReactiveHandler;
2546
2660
  exports.defaultMapReactiveHandler = defaultMapReactiveHandler;
2547
2661
  exports.defaultObjectReactiveHandler = defaultObjectReactiveHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.5",
4
4
  "description": "Viewfly is a simple and easy-to-use JavaScript framework with an intuitive development experience.",
5
5
  "main": "./bundles/index.js",
6
6
  "module": "./bundles/index.esm.js",
@@ -50,7 +50,7 @@
50
50
  "bugs": {
51
51
  "url": "https://github.com/viewfly/viewfly.git/issues"
52
52
  },
53
- "gitHead": "1abff2eeba5cf840be260638c73651bf93bb706c",
53
+ "gitHead": "4033e6f38e517c754bea8786459eba0e0f2197d9",
54
54
  "dependencies": {
55
55
  "reflect-metadata": "^0.2.2"
56
56
  }