@viewfly/core 2.0.0-alpha.4 → 2.0.0-alpha.6

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.
@@ -211,7 +211,7 @@ declare function comparePropsWithCallbacks(oldProps: Record<string, any>, newPro
211
211
  declare const TextAtomType: unique symbol;
212
212
  declare const ElementAtomType: unique symbol;
213
213
  declare const ComponentAtomType: unique symbol;
214
- type ElementNamespace = string | undefined;
214
+ type ElementNamespace = string | void;
215
215
  interface TextAtom {
216
216
  type: typeof TextAtomType;
217
217
  index: number;
@@ -264,6 +264,7 @@ declare abstract class NativeRenderer<ElementNode = NativeNode, TextNode = Nativ
264
264
  abstract cleanChildren(node: ElementNode, namespace: ElementNamespace): void;
265
265
  abstract syncTextContent(target: TextNode, content: string, namespace: ElementNamespace): void;
266
266
  abstract insertAfter(newNode: ElementNode | TextNode, ref: ElementNode | TextNode, namespace: ElementNamespace): void;
267
+ abstract getNameSpace(type: string, namespace: ElementNamespace): string | void;
267
268
  }
268
269
 
269
270
  interface RefListener<T> {
@@ -436,8 +437,19 @@ declare class Component {
436
437
  * 获取当前组件实例
437
438
  */
438
439
  declare function getCurrentInstance(): Component;
440
+ declare function registryComponentDestroyCallback(fn: () => void): void;
439
441
 
440
442
  declare function createContext(providers: Provider[], scope?: Scope | null, parentInjector?: Injector): (props: Props) => () => JSXNode | JSXNode[];
443
+ interface ContextProviderParams<T> {
444
+ provide: Type<T> | AbstractType<T> | InjectionToken<T>;
445
+ }
446
+ interface ContextProvider<T> extends Props {
447
+ useClass?: ClassProvider<T>['useClass'];
448
+ useFactory?: FactoryProvider<T>['useFactory'];
449
+ useValue?: ValueProvider<T>['useValue'];
450
+ useExisting?: ExistingProvider<T>['useExisting'];
451
+ }
452
+ declare function createContextProvider<T>(params: ContextProviderParams<T>): (props: ContextProvider<T>) => () => ViewFlyNode<string | ComponentSetup<any>>;
441
453
  /**
442
454
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
443
455
  */
@@ -467,12 +479,18 @@ interface ComponentAnnotation {
467
479
  */
468
480
  declare function withAnnotation<T extends ComponentSetup>(annotation: ComponentAnnotation, componentSetup: T): T;
469
481
 
482
+ declare class Dep {
483
+ effect: () => void;
484
+ destroyCallbacks: Array<() => void>;
485
+ constructor(effect: () => void);
486
+ destroy(): void;
487
+ }
488
+ declare function getDepContext(): Dep | undefined;
489
+ declare function pushDepContext(dep: Dep): void;
490
+ declare function popDepContext(): void;
491
+
470
492
  declare function withMemo<T extends Props = Props>(canUseMemo: ComponentInstance<T>['$useMemo'], render: () => JSXNode): ComponentInstance<T>;
471
493
 
472
- declare const ElementNamespaceMap: {
473
- readonly svg: "svg";
474
- readonly math: "mathml";
475
- };
476
494
  declare function createRenderer(component: Component, nativeRenderer: NativeRenderer, namespace: ElementNamespace): (host: NativeNode) => void;
477
495
 
478
496
  /**
@@ -518,15 +536,6 @@ interface Computed<T> {
518
536
  }
519
537
  declare function computed<T>(callback: () => T, isContinue?: (data: T) => unknown): Computed<T>;
520
538
 
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
539
  declare enum TrackOpTypes {
531
540
  Get = "Get",
532
541
  Has = "Has",
@@ -540,7 +549,6 @@ declare enum TriggerOpTypes {
540
549
  }
541
550
  declare function track(target: object, type: TrackOpTypes, key?: unknown): void;
542
551
  declare function trigger(target: object, type: TriggerOpTypes, key?: unknown): void;
543
- declare function registryComponentDestroyCallback(fn: () => void): void;
544
552
 
545
553
  declare const rawToProxyCache: WeakMap<object, any>;
546
554
  declare const proxyToRawCache: WeakMap<object, any>;
@@ -640,4 +648,74 @@ declare function shallowReactive<T>(raw: T): T;
640
648
 
641
649
  declare function watch<T>(trigger: () => T, callback: (newValue: T, oldValue: T) => (() => any) | void): () => void;
642
650
 
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 };
651
+ /**
652
+ * 组件状态实例,直接调用可以获取最新的状态,通过 set 方法可以更新状态
653
+ */
654
+ interface Signal<T> {
655
+ /**
656
+ * 直接调用一个 Signal 实例,可以获取最新状态
657
+ */
658
+ (): T;
659
+ /**
660
+ * 更新组件状态的方法,可以传入最新的值
661
+ * @param newState
662
+ */
663
+ set(newState: T): void;
664
+ }
665
+ /**
666
+ * 组件状态管理器
667
+ * @param state 初始状态
668
+ * @example
669
+ * ```tsx
670
+ * function App() {
671
+ * // 初始化状态
672
+ * const state = createSignal(1)
673
+ *
674
+ * return () => {
675
+ * <div>
676
+ * <div>当前值为:{state()}</div>
677
+ * <div>
678
+ * <button type="button" onClick={() => {
679
+ * // 当点击时更新状态
680
+ * state.set(state() + 1)
681
+ * }
682
+ * }>updateState</button>
683
+ * </div>
684
+ * </div>
685
+ * }
686
+ * }
687
+ */
688
+ declare function createSignal<T>(state: T): Signal<T>;
689
+
690
+ /**
691
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
692
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
693
+ *
694
+ * @param fn
695
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
696
+ */
697
+ declare function createDerived<T>(fn: () => T, isContinue?: (data: T) => unknown): Signal<T>;
698
+
699
+ interface EffectCallback<T> {
700
+ (newValue: T, oldValue: T): void | (() => void);
701
+ }
702
+ /**
703
+ * 监听状态变化,当任意一个状态发生变更时,触发回调。
704
+ * createEffect 会返回一个取消监听的函数,调用此函数,可以取消监听。
705
+ * 当在组件中调用时,组件销毁时会自动取消监听。
706
+ * @param deps 依赖的状态 Signal,可以是一个 Signal,只可以一个数包含 Signal 的数组,或者是一个求值函数
707
+ * @param callback 状态变更后的回调函数
708
+ */
709
+ declare function createEffect<T>(deps: Signal<T>, callback: EffectCallback<T>): () => void;
710
+ declare function createEffect<T>(deps: [Signal<T>], callback: EffectCallback<[T]>): () => void;
711
+ declare function createEffect<T, T1>(deps: [Signal<T>, Signal<T1>], callback: EffectCallback<[T, T1]>): () => void;
712
+ declare function createEffect<T, T1, T2>(deps: [Signal<T>, Signal<T1>, Signal<T2>], callback: EffectCallback<[T, T1, T2]>): () => void;
713
+ declare function createEffect<T, T1, T2, T3>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>], callback: EffectCallback<[T, T1, T2, T3]>): () => void;
714
+ 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;
715
+ 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;
716
+ 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;
717
+ 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;
718
+ declare function createEffect<T>(deps: () => T, callback: EffectCallback<T>): () => void;
719
+ declare function createEffect<T = any>(deps: Signal<any>[], callback: EffectCallback<T[]>): () => void;
720
+
721
+ 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, type ContextProvider, type ContextProviderParams, Dep, DynamicRef, type EffectCallback, type ElementNamespace, 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, 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, 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,62 @@ 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
+ }
1636
+
1637
+ function Fragment(props) {
1638
+ return () => {
1639
+ return props.children;
1640
+ };
1641
+ }
1642
+ function jsx(type, props, key) {
1643
+ return JSXNodeFactory.createNode(type, props, key);
1644
+ }
1645
+ const jsxs = jsx;
1646
+ const JSXNodeFactory = {
1647
+ createNode(type, props, key) {
1648
+ return {
1649
+ type,
1650
+ props,
1651
+ key
1652
+ };
1653
+ }
1654
+ };
1655
+
1656
+ function watch(trigger, callback) {
1657
+ let prevFn;
1658
+ const dep = new Dep(() => {
1659
+ pushDepContext(dep);
1660
+ const newValue = trigger();
1661
+ popDepContext();
1662
+ if (newValue === oldValue) {
1663
+ return;
1664
+ }
1665
+ if (prevFn) {
1666
+ prevFn();
1667
+ }
1668
+ prevFn = callback(newValue, oldValue);
1669
+ oldValue = newValue;
1670
+ });
1671
+ pushDepContext(dep);
1672
+ let oldValue = trigger();
1673
+ popDepContext();
1674
+ dep.destroyCallbacks.push(() => {
1675
+ prevFn === null || prevFn === void 0 ? void 0 : prevFn();
1676
+ });
1677
+ function unWatch() {
1678
+ dep.destroy();
1679
+ }
1680
+ registryComponentDestroyCallback(unWatch);
1681
+ return unWatch;
1682
+ }
1635
1683
 
1636
1684
  const injectMap = new WeakMap();
1637
1685
  function getInjector(start) {
@@ -1654,6 +1702,19 @@ function createContext(providers, scope, parentInjector) {
1654
1702
  };
1655
1703
  };
1656
1704
  }
1705
+ function createContextProvider(params) {
1706
+ return function contextProvider(props) {
1707
+ let Context = createContext([Object.assign({ provide: params.provide }, props)]);
1708
+ watch(() => {
1709
+ return props.useClass || props.useFactory || props.useValue || props.useExisting;
1710
+ }, () => {
1711
+ Context = createContext([Object.assign({ provide: params.provide }, props)]);
1712
+ });
1713
+ return () => {
1714
+ return jsx(Context, { children: props.children });
1715
+ };
1716
+ };
1717
+ }
1657
1718
  /**
1658
1719
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
1659
1720
  */
@@ -1699,25 +1760,6 @@ function withAnnotation(annotation, componentSetup) {
1699
1760
  class NativeRenderer {
1700
1761
  }
1701
1762
 
1702
- function Fragment(props) {
1703
- return () => {
1704
- return props.children;
1705
- };
1706
- }
1707
- function jsx(type, props, key) {
1708
- return JSXNodeFactory.createNode(type, props, key);
1709
- }
1710
- const jsxs = jsx;
1711
- const JSXNodeFactory = {
1712
- createNode(type, props, key) {
1713
- return {
1714
- type,
1715
- props,
1716
- key
1717
- };
1718
- }
1719
- };
1720
-
1721
1763
  function withMemo(canUseMemo, render) {
1722
1764
  return {
1723
1765
  $useMemo: canUseMemo,
@@ -1725,10 +1767,6 @@ function withMemo(canUseMemo, render) {
1725
1767
  };
1726
1768
  }
1727
1769
 
1728
- const ElementNamespaceMap = {
1729
- svg: 'svg',
1730
- math: 'mathml',
1731
- };
1732
1770
  const listenerReg = /^on[A-Z]/;
1733
1771
  function createRenderer(component, nativeRenderer, namespace) {
1734
1772
  let isInit = true;
@@ -1779,7 +1817,7 @@ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1779
1817
  }
1780
1818
  function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
1781
1819
  const newTemplate = component.rerender();
1782
- newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1820
+ newAtom.child = createChildChain(newTemplate, nativeRenderer, newAtom.namespace);
1783
1821
  diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
1784
1822
  }
1785
1823
  function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
@@ -1812,11 +1850,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1812
1850
  }
1813
1851
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1814
1852
  const commits = [];
1815
- function changeOffset() {
1816
- offset++;
1817
- }
1818
1853
  while (newAtom) {
1819
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1854
+ oldAtom = createChanges(newAtom, oldAtom, commits);
1820
1855
  newAtom = newAtom.sibling;
1821
1856
  }
1822
1857
  let dirtyDiffAtom = oldAtom;
@@ -1827,7 +1862,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1827
1862
  let offset = 0;
1828
1863
  const len = commits.length;
1829
1864
  for (let i = 0; i < len; i++) {
1830
- const commit = commits[i];
1831
1865
  while (oldAtom) {
1832
1866
  if (oldAtom.index <= i) {
1833
1867
  offset--;
@@ -1836,27 +1870,34 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1836
1870
  }
1837
1871
  break;
1838
1872
  }
1839
- commit.callback(commit.params, offset, needMove);
1873
+ const { dirtyAtom, newAtom } = commits[i];
1874
+ if (dirtyAtom) {
1875
+ switch (dirtyAtom.type) {
1876
+ case ElementAtomType:
1877
+ updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, dirtyAtom);
1878
+ break;
1879
+ case TextAtomType:
1880
+ updateText(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1881
+ break;
1882
+ case ComponentAtomType:
1883
+ updateComponent(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1884
+ break;
1885
+ }
1886
+ }
1887
+ else {
1888
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1889
+ offset++;
1890
+ }
1840
1891
  }
1841
1892
  }
1842
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1893
+ function createChanges(newAtom, oldAtom, commits) {
1843
1894
  const startDiffAtom = oldAtom;
1844
1895
  let prev = null;
1845
1896
  while (oldAtom) {
1846
- const newAtomType = newAtom.type;
1847
- if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1897
+ if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1848
1898
  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
- }
1899
+ dirtyAtom: oldAtom,
1900
+ newAtom
1860
1901
  });
1861
1902
  const next = oldAtom.sibling;
1862
1903
  if (!prev) {
@@ -1869,25 +1910,12 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1869
1910
  oldAtom = oldAtom.sibling;
1870
1911
  }
1871
1912
  commits.push({
1872
- callback: patchUpdate,
1873
- params: {
1874
- oldAtom: oldAtom,
1875
- newAtom,
1876
- nativeRenderer,
1877
- context,
1878
- effect,
1879
- parentComponent
1880
- }
1913
+ dirtyAtom: null,
1914
+ newAtom
1881
1915
  });
1882
1916
  return startDiffAtom;
1883
1917
  }
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;
1918
+ function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1891
1919
  const nativeNode = oldAtom.nativeNode;
1892
1920
  newAtom.nativeNode = nativeNode;
1893
1921
  if (needMove || newAtom.index - offset !== oldAtom.index) {
@@ -1896,23 +1924,21 @@ function updateText(params, offset, needMove) {
1896
1924
  context.host = nativeNode;
1897
1925
  context.isParent = false;
1898
1926
  }
1899
- function updateElement(params, offset, needMove) {
1900
- const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1901
- newAtom.nativeNode = oldAtom.nativeNode;
1927
+ function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
1928
+ const nativeNode = oldAtom.nativeNode;
1929
+ newAtom.nativeNode = nativeNode;
1902
1930
  if (needMove || newAtom.index - offset !== oldAtom.index) {
1903
1931
  insertNode(nativeRenderer, newAtom, context);
1904
1932
  }
1905
- context.host = newAtom.nativeNode;
1933
+ context.host = nativeNode;
1906
1934
  context.isParent = false;
1907
1935
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1908
- host: newAtom.nativeNode,
1936
+ host: nativeNode,
1909
1937
  isParent: true,
1910
1938
  rootHost: context.rootHost
1911
1939
  });
1912
1940
  }
1913
- function updateComponent(params, offset, needMove) {
1914
- const { oldAtom, newAtom, nativeRenderer } = params;
1915
- let context = params.context;
1941
+ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1916
1942
  const component = oldAtom.jsxNode;
1917
1943
  const portalHost = component.instance.$portalHost;
1918
1944
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
@@ -1936,7 +1962,7 @@ function updateComponent(params, offset, needMove) {
1936
1962
  }
1937
1963
  else {
1938
1964
  newAtom.child = oldAtom.child;
1939
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate);
1965
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate || !component.changedSubComponents.size);
1940
1966
  }
1941
1967
  component.rendered();
1942
1968
  }
@@ -1953,7 +1979,9 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1953
1979
  if (moveView) {
1954
1980
  insertNode(nativeRenderer, atom, context);
1955
1981
  }
1956
- reuseElementChildrenView(nativeRenderer, atom);
1982
+ if (!skipSubComponentDiff) {
1983
+ reuseElementChildrenView(nativeRenderer, atom);
1984
+ }
1957
1985
  context.isParent = false;
1958
1986
  context.host = atom.nativeNode;
1959
1987
  }
@@ -1963,7 +1991,7 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1963
1991
  child = child.sibling;
1964
1992
  }
1965
1993
  }
1966
- function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
1994
+ function reuseElementChildrenView(nativeRenderer, atom, context) {
1967
1995
  let child = atom.child;
1968
1996
  while (child) {
1969
1997
  if (child.jsxNode instanceof Component) {
@@ -2012,7 +2040,7 @@ function cleanChildren(atom, nativeRenderer, needClean) {
2012
2040
  }
2013
2041
  function componentRender(nativeRenderer, component, from, context) {
2014
2042
  component.render((template, portalHost) => {
2015
- from.child = createChildChain(template, from.namespace);
2043
+ from.child = createChildChain(template, nativeRenderer, from.namespace);
2016
2044
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
2017
2045
  component.viewMetadata = Object.assign({ atom: from }, context);
2018
2046
  let child = from.child;
@@ -2037,7 +2065,7 @@ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key)
2037
2065
  prevAtom.sibling = atom;
2038
2066
  return atom;
2039
2067
  }
2040
- function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2068
+ function createChainByNode(jsxNode, prevAtom, nativeRenderer, elementNamespace) {
2041
2069
  const type = typeof jsxNode;
2042
2070
  if (jsxNode != null && type !== 'boolean') {
2043
2071
  if (type === 'string') {
@@ -2045,11 +2073,11 @@ function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2045
2073
  }
2046
2074
  if (type === 'object') {
2047
2075
  if (Array.isArray(jsxNode)) {
2048
- return createChainByChildren(jsxNode, prevAtom, elementNamespace);
2076
+ return createChainByChildren(jsxNode, prevAtom, nativeRenderer, elementNamespace);
2049
2077
  }
2050
2078
  const nodeType = typeof jsxNode.type;
2051
2079
  if (nodeType === 'string') {
2052
- return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace || ElementNamespaceMap[jsxNode.type], jsxNode.key);
2080
+ return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, nativeRenderer.getNameSpace(jsxNode.type, elementNamespace), jsxNode.key);
2053
2081
  }
2054
2082
  else if (nodeType === 'function') {
2055
2083
  return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace, jsxNode.key);
@@ -2060,17 +2088,17 @@ function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2060
2088
  }
2061
2089
  return prevAtom;
2062
2090
  }
2063
- function createChainByChildren(children, prevAtom, elementNamespace) {
2091
+ function createChainByChildren(children, prevAtom, nativeRenderer, elementNamespace) {
2064
2092
  const len = children.length;
2065
2093
  for (let i = 0; i < len; i++) {
2066
2094
  const item = children[i];
2067
- prevAtom = createChainByNode(item, prevAtom, elementNamespace);
2095
+ prevAtom = createChainByNode(item, prevAtom, nativeRenderer, elementNamespace);
2068
2096
  }
2069
2097
  return prevAtom;
2070
2098
  }
2071
- function createChildChain(template, namespace) {
2099
+ function createChildChain(template, nativeRenderer, namespace) {
2072
2100
  const beforeAtom = { sibling: null, index: -1 };
2073
- createChainByNode(template, beforeAtom, namespace);
2101
+ createChainByNode(template, beforeAtom, nativeRenderer, namespace);
2074
2102
  return beforeAtom.sibling;
2075
2103
  }
2076
2104
  function insertNode(nativeRenderer, atom, context) {
@@ -2086,11 +2114,9 @@ function insertNode(nativeRenderer, atom, context) {
2086
2114
  nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
2087
2115
  }
2088
2116
  }
2089
- function createElementChildren(type, children, namespace) {
2090
- if (type === 'foreignObject' && namespace === ElementNamespaceMap.svg) {
2091
- return createChildChain(children, void 0);
2092
- }
2093
- return createChildChain(children, namespace);
2117
+ function createElementChildren(type, children, nativeRenderer, namespace) {
2118
+ const ns = nativeRenderer.getNameSpace(type, namespace);
2119
+ return createChildChain(children, nativeRenderer, ns);
2094
2120
  }
2095
2121
  function createElement(nativeRenderer, atom, parentComponent, context) {
2096
2122
  const { namespace, jsxNode } = atom;
@@ -2099,7 +2125,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2099
2125
  let bindingRefs;
2100
2126
  for (const key in props) {
2101
2127
  if (key === 'children') {
2102
- atom.child = createElementChildren(jsxNode.type, props.children, namespace);
2128
+ atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
2103
2129
  continue;
2104
2130
  }
2105
2131
  if (key === 'class') {
@@ -2190,7 +2216,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2190
2216
  }, (key, value) => {
2191
2217
  if (key === 'children') {
2192
2218
  updatedChildren = true;
2193
- newAtom.child = createElementChildren(newVNode.type, value, isSvg);
2219
+ newAtom.child = createElementChildren(newVNode.type, value, nativeRenderer, isSvg);
2194
2220
  buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
2195
2221
  return;
2196
2222
  }
@@ -2219,7 +2245,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2219
2245
  }, (key, newValue, oldValue) => {
2220
2246
  if (key === 'children') {
2221
2247
  updatedChildren = true;
2222
- newAtom.child = createElementChildren(newVNode.type, newValue, isSvg);
2248
+ newAtom.child = createElementChildren(newVNode.type, newValue, nativeRenderer, isSvg);
2223
2249
  if (!newAtom.child) {
2224
2250
  cleanElementChildren(oldAtom, nativeRenderer);
2225
2251
  }
@@ -2263,7 +2289,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2263
2289
  });
2264
2290
  if (!updatedChildren) {
2265
2291
  newAtom.child = oldAtom.child;
2266
- reuseElementChildrenView(nativeRenderer, newAtom);
2292
+ // reuseElementChildrenView(nativeRenderer, newAtom, context)
2267
2293
  }
2268
2294
  applyRefs(unBindRefs, nativeNode, false);
2269
2295
  applyRefs(bindRefs, nativeNode, true);
@@ -2480,32 +2506,123 @@ function shallowReactive(raw) {
2480
2506
  return proxy;
2481
2507
  }
2482
2508
 
2483
- function watch(trigger, callback) {
2484
- let prevFn;
2485
- const dep = new Dep(() => {
2486
- pushDepContext(dep);
2487
- const newValue = trigger();
2488
- popDepContext();
2489
- if (newValue === oldValue) {
2509
+ /**
2510
+ * 组件状态管理器
2511
+ * @param state 初始状态
2512
+ * @example
2513
+ * ```tsx
2514
+ * function App() {
2515
+ * // 初始化状态
2516
+ * const state = createSignal(1)
2517
+ *
2518
+ * return () => {
2519
+ * <div>
2520
+ * <div>当前值为:{state()}</div>
2521
+ * <div>
2522
+ * <button type="button" onClick={() => {
2523
+ * // 当点击时更新状态
2524
+ * state.set(state() + 1)
2525
+ * }
2526
+ * }>updateState</button>
2527
+ * </div>
2528
+ * </div>
2529
+ * }
2530
+ * }
2531
+ */
2532
+ function createSignal(state) {
2533
+ const subscribers = new Set();
2534
+ function signal() {
2535
+ const listener = getDepContext();
2536
+ if (listener && !subscribers.has(listener)) {
2537
+ listener.destroyCallbacks.push(() => {
2538
+ subscribers.delete(listener);
2539
+ });
2540
+ subscribers.add(listener);
2541
+ }
2542
+ return state;
2543
+ }
2544
+ signal.set = function (newValue) {
2545
+ if (newValue === state) {
2490
2546
  return;
2491
2547
  }
2548
+ state = newValue;
2549
+ const listeners = Array.from(subscribers);
2550
+ listeners.forEach(listener => listener.effect());
2551
+ };
2552
+ return signal;
2553
+ }
2554
+
2555
+ /**
2556
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
2557
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
2558
+ *
2559
+ * @param fn
2560
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
2561
+ */
2562
+ function createDerived(fn, isContinue) {
2563
+ let isStop = false;
2564
+ function canListen(value) {
2565
+ if (isContinue) {
2566
+ const b = isContinue(value);
2567
+ if (b === false) {
2568
+ listener.destroy();
2569
+ return false;
2570
+ }
2571
+ }
2572
+ return true;
2573
+ }
2574
+ const listener = new Dep(() => {
2575
+ if (isStop) {
2576
+ return;
2577
+ }
2578
+ isStop = true;
2579
+ listener.destroy();
2580
+ pushDepContext(listener);
2581
+ const value = fn();
2582
+ popDepContext();
2583
+ signal.set(value);
2584
+ canListen(value);
2585
+ isStop = false;
2586
+ });
2587
+ pushDepContext(listener);
2588
+ const value = fn();
2589
+ const signal = createSignal(value);
2590
+ popDepContext();
2591
+ isStop = false;
2592
+ if (canListen(value)) {
2593
+ registryComponentDestroyCallback(() => listener.destroy());
2594
+ }
2595
+ return signal;
2596
+ }
2597
+
2598
+ /* eslint-enable max-len*/
2599
+ function createEffect(deps, callback) {
2600
+ let prevFn;
2601
+ const isArray = Array.isArray(deps);
2602
+ const effect = new Dep(function () {
2492
2603
  if (prevFn) {
2493
2604
  prevFn();
2494
2605
  }
2606
+ const newValue = isArray ? deps.map(fn => fn()) : deps();
2495
2607
  prevFn = callback(newValue, oldValue);
2496
2608
  oldValue = newValue;
2497
2609
  });
2498
- pushDepContext(dep);
2499
- let oldValue = trigger();
2610
+ pushDepContext(effect);
2611
+ let oldValue = isArray ? deps.map(fn => fn()) : deps();
2500
2612
  popDepContext();
2501
- dep.destroyCallbacks.push(() => {
2502
- prevFn === null || prevFn === void 0 ? void 0 : prevFn();
2503
- });
2613
+ let isUnWatch = false;
2504
2614
  function unWatch() {
2505
- dep.destroy();
2615
+ if (isUnWatch) {
2616
+ return;
2617
+ }
2618
+ isUnWatch = true;
2619
+ if (prevFn) {
2620
+ prevFn();
2621
+ }
2622
+ effect.destroy();
2506
2623
  }
2507
2624
  registryComponentDestroyCallback(unWatch);
2508
2625
  return unWatch;
2509
2626
  }
2510
2627
 
2511
- 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 };
2628
+ export { ArrayReactiveHandler, Component, Dep, DynamicRef, 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, 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, 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,62 @@ 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
+ }
1638
+
1639
+ function Fragment(props) {
1640
+ return () => {
1641
+ return props.children;
1642
+ };
1643
+ }
1644
+ function jsx(type, props, key) {
1645
+ return JSXNodeFactory.createNode(type, props, key);
1646
+ }
1647
+ const jsxs = jsx;
1648
+ const JSXNodeFactory = {
1649
+ createNode(type, props, key) {
1650
+ return {
1651
+ type,
1652
+ props,
1653
+ key
1654
+ };
1655
+ }
1656
+ };
1657
+
1658
+ function watch(trigger, callback) {
1659
+ let prevFn;
1660
+ const dep = new Dep(() => {
1661
+ pushDepContext(dep);
1662
+ const newValue = trigger();
1663
+ popDepContext();
1664
+ if (newValue === oldValue) {
1665
+ return;
1666
+ }
1667
+ if (prevFn) {
1668
+ prevFn();
1669
+ }
1670
+ prevFn = callback(newValue, oldValue);
1671
+ oldValue = newValue;
1672
+ });
1673
+ pushDepContext(dep);
1674
+ let oldValue = trigger();
1675
+ popDepContext();
1676
+ dep.destroyCallbacks.push(() => {
1677
+ prevFn === null || prevFn === void 0 ? void 0 : prevFn();
1678
+ });
1679
+ function unWatch() {
1680
+ dep.destroy();
1681
+ }
1682
+ registryComponentDestroyCallback(unWatch);
1683
+ return unWatch;
1684
+ }
1637
1685
 
1638
1686
  const injectMap = new WeakMap();
1639
1687
  function getInjector(start) {
@@ -1656,6 +1704,19 @@ function createContext(providers, scope, parentInjector) {
1656
1704
  };
1657
1705
  };
1658
1706
  }
1707
+ function createContextProvider(params) {
1708
+ return function contextProvider(props) {
1709
+ let Context = createContext([Object.assign({ provide: params.provide }, props)]);
1710
+ watch(() => {
1711
+ return props.useClass || props.useFactory || props.useValue || props.useExisting;
1712
+ }, () => {
1713
+ Context = createContext([Object.assign({ provide: params.provide }, props)]);
1714
+ });
1715
+ return () => {
1716
+ return jsx(Context, { children: props.children });
1717
+ };
1718
+ };
1719
+ }
1659
1720
  /**
1660
1721
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
1661
1722
  */
@@ -1701,25 +1762,6 @@ function withAnnotation(annotation, componentSetup) {
1701
1762
  class NativeRenderer {
1702
1763
  }
1703
1764
 
1704
- function Fragment(props) {
1705
- return () => {
1706
- return props.children;
1707
- };
1708
- }
1709
- function jsx(type, props, key) {
1710
- return JSXNodeFactory.createNode(type, props, key);
1711
- }
1712
- const jsxs = jsx;
1713
- const JSXNodeFactory = {
1714
- createNode(type, props, key) {
1715
- return {
1716
- type,
1717
- props,
1718
- key
1719
- };
1720
- }
1721
- };
1722
-
1723
1765
  function withMemo(canUseMemo, render) {
1724
1766
  return {
1725
1767
  $useMemo: canUseMemo,
@@ -1727,10 +1769,6 @@ function withMemo(canUseMemo, render) {
1727
1769
  };
1728
1770
  }
1729
1771
 
1730
- const ElementNamespaceMap = {
1731
- svg: 'svg',
1732
- math: 'mathml',
1733
- };
1734
1772
  const listenerReg = /^on[A-Z]/;
1735
1773
  function createRenderer(component, nativeRenderer, namespace) {
1736
1774
  let isInit = true;
@@ -1781,7 +1819,7 @@ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1781
1819
  }
1782
1820
  function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
1783
1821
  const newTemplate = component.rerender();
1784
- newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1822
+ newAtom.child = createChildChain(newTemplate, nativeRenderer, newAtom.namespace);
1785
1823
  diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
1786
1824
  }
1787
1825
  function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
@@ -1814,11 +1852,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1814
1852
  }
1815
1853
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1816
1854
  const commits = [];
1817
- function changeOffset() {
1818
- offset++;
1819
- }
1820
1855
  while (newAtom) {
1821
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1856
+ oldAtom = createChanges(newAtom, oldAtom, commits);
1822
1857
  newAtom = newAtom.sibling;
1823
1858
  }
1824
1859
  let dirtyDiffAtom = oldAtom;
@@ -1829,7 +1864,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1829
1864
  let offset = 0;
1830
1865
  const len = commits.length;
1831
1866
  for (let i = 0; i < len; i++) {
1832
- const commit = commits[i];
1833
1867
  while (oldAtom) {
1834
1868
  if (oldAtom.index <= i) {
1835
1869
  offset--;
@@ -1838,27 +1872,34 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1838
1872
  }
1839
1873
  break;
1840
1874
  }
1841
- commit.callback(commit.params, offset, needMove);
1875
+ const { dirtyAtom, newAtom } = commits[i];
1876
+ if (dirtyAtom) {
1877
+ switch (dirtyAtom.type) {
1878
+ case ElementAtomType:
1879
+ updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, dirtyAtom);
1880
+ break;
1881
+ case TextAtomType:
1882
+ updateText(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1883
+ break;
1884
+ case ComponentAtomType:
1885
+ updateComponent(nativeRenderer, context, offset, needMove, newAtom, dirtyAtom);
1886
+ break;
1887
+ }
1888
+ }
1889
+ else {
1890
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1891
+ offset++;
1892
+ }
1842
1893
  }
1843
1894
  }
1844
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1895
+ function createChanges(newAtom, oldAtom, commits) {
1845
1896
  const startDiffAtom = oldAtom;
1846
1897
  let prev = null;
1847
1898
  while (oldAtom) {
1848
- const newAtomType = newAtom.type;
1849
- if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1899
+ if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1850
1900
  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
- }
1901
+ dirtyAtom: oldAtom,
1902
+ newAtom
1862
1903
  });
1863
1904
  const next = oldAtom.sibling;
1864
1905
  if (!prev) {
@@ -1871,25 +1912,12 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1871
1912
  oldAtom = oldAtom.sibling;
1872
1913
  }
1873
1914
  commits.push({
1874
- callback: patchUpdate,
1875
- params: {
1876
- oldAtom: oldAtom,
1877
- newAtom,
1878
- nativeRenderer,
1879
- context,
1880
- effect,
1881
- parentComponent
1882
- }
1915
+ dirtyAtom: null,
1916
+ newAtom
1883
1917
  });
1884
1918
  return startDiffAtom;
1885
1919
  }
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;
1920
+ function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1893
1921
  const nativeNode = oldAtom.nativeNode;
1894
1922
  newAtom.nativeNode = nativeNode;
1895
1923
  if (needMove || newAtom.index - offset !== oldAtom.index) {
@@ -1898,23 +1926,21 @@ function updateText(params, offset, needMove) {
1898
1926
  context.host = nativeNode;
1899
1927
  context.isParent = false;
1900
1928
  }
1901
- function updateElement(params, offset, needMove) {
1902
- const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1903
- newAtom.nativeNode = oldAtom.nativeNode;
1929
+ function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
1930
+ const nativeNode = oldAtom.nativeNode;
1931
+ newAtom.nativeNode = nativeNode;
1904
1932
  if (needMove || newAtom.index - offset !== oldAtom.index) {
1905
1933
  insertNode(nativeRenderer, newAtom, context);
1906
1934
  }
1907
- context.host = newAtom.nativeNode;
1935
+ context.host = nativeNode;
1908
1936
  context.isParent = false;
1909
1937
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1910
- host: newAtom.nativeNode,
1938
+ host: nativeNode,
1911
1939
  isParent: true,
1912
1940
  rootHost: context.rootHost
1913
1941
  });
1914
1942
  }
1915
- function updateComponent(params, offset, needMove) {
1916
- const { oldAtom, newAtom, nativeRenderer } = params;
1917
- let context = params.context;
1943
+ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1918
1944
  const component = oldAtom.jsxNode;
1919
1945
  const portalHost = component.instance.$portalHost;
1920
1946
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
@@ -1938,7 +1964,7 @@ function updateComponent(params, offset, needMove) {
1938
1964
  }
1939
1965
  else {
1940
1966
  newAtom.child = oldAtom.child;
1941
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate);
1967
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate || !component.changedSubComponents.size);
1942
1968
  }
1943
1969
  component.rendered();
1944
1970
  }
@@ -1955,7 +1981,9 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1955
1981
  if (moveView) {
1956
1982
  insertNode(nativeRenderer, atom, context);
1957
1983
  }
1958
- reuseElementChildrenView(nativeRenderer, atom);
1984
+ if (!skipSubComponentDiff) {
1985
+ reuseElementChildrenView(nativeRenderer, atom);
1986
+ }
1959
1987
  context.isParent = false;
1960
1988
  context.host = atom.nativeNode;
1961
1989
  }
@@ -1965,7 +1993,7 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1965
1993
  child = child.sibling;
1966
1994
  }
1967
1995
  }
1968
- function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
1996
+ function reuseElementChildrenView(nativeRenderer, atom, context) {
1969
1997
  let child = atom.child;
1970
1998
  while (child) {
1971
1999
  if (child.jsxNode instanceof Component) {
@@ -2014,7 +2042,7 @@ function cleanChildren(atom, nativeRenderer, needClean) {
2014
2042
  }
2015
2043
  function componentRender(nativeRenderer, component, from, context) {
2016
2044
  component.render((template, portalHost) => {
2017
- from.child = createChildChain(template, from.namespace);
2045
+ from.child = createChildChain(template, nativeRenderer, from.namespace);
2018
2046
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
2019
2047
  component.viewMetadata = Object.assign({ atom: from }, context);
2020
2048
  let child = from.child;
@@ -2039,7 +2067,7 @@ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key)
2039
2067
  prevAtom.sibling = atom;
2040
2068
  return atom;
2041
2069
  }
2042
- function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2070
+ function createChainByNode(jsxNode, prevAtom, nativeRenderer, elementNamespace) {
2043
2071
  const type = typeof jsxNode;
2044
2072
  if (jsxNode != null && type !== 'boolean') {
2045
2073
  if (type === 'string') {
@@ -2047,11 +2075,11 @@ function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2047
2075
  }
2048
2076
  if (type === 'object') {
2049
2077
  if (Array.isArray(jsxNode)) {
2050
- return createChainByChildren(jsxNode, prevAtom, elementNamespace);
2078
+ return createChainByChildren(jsxNode, prevAtom, nativeRenderer, elementNamespace);
2051
2079
  }
2052
2080
  const nodeType = typeof jsxNode.type;
2053
2081
  if (nodeType === 'string') {
2054
- return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace || ElementNamespaceMap[jsxNode.type], jsxNode.key);
2082
+ return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, nativeRenderer.getNameSpace(jsxNode.type, elementNamespace), jsxNode.key);
2055
2083
  }
2056
2084
  else if (nodeType === 'function') {
2057
2085
  return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace, jsxNode.key);
@@ -2062,17 +2090,17 @@ function createChainByNode(jsxNode, prevAtom, elementNamespace) {
2062
2090
  }
2063
2091
  return prevAtom;
2064
2092
  }
2065
- function createChainByChildren(children, prevAtom, elementNamespace) {
2093
+ function createChainByChildren(children, prevAtom, nativeRenderer, elementNamespace) {
2066
2094
  const len = children.length;
2067
2095
  for (let i = 0; i < len; i++) {
2068
2096
  const item = children[i];
2069
- prevAtom = createChainByNode(item, prevAtom, elementNamespace);
2097
+ prevAtom = createChainByNode(item, prevAtom, nativeRenderer, elementNamespace);
2070
2098
  }
2071
2099
  return prevAtom;
2072
2100
  }
2073
- function createChildChain(template, namespace) {
2101
+ function createChildChain(template, nativeRenderer, namespace) {
2074
2102
  const beforeAtom = { sibling: null, index: -1 };
2075
- createChainByNode(template, beforeAtom, namespace);
2103
+ createChainByNode(template, beforeAtom, nativeRenderer, namespace);
2076
2104
  return beforeAtom.sibling;
2077
2105
  }
2078
2106
  function insertNode(nativeRenderer, atom, context) {
@@ -2088,11 +2116,9 @@ function insertNode(nativeRenderer, atom, context) {
2088
2116
  nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
2089
2117
  }
2090
2118
  }
2091
- function createElementChildren(type, children, namespace) {
2092
- if (type === 'foreignObject' && namespace === ElementNamespaceMap.svg) {
2093
- return createChildChain(children, void 0);
2094
- }
2095
- return createChildChain(children, namespace);
2119
+ function createElementChildren(type, children, nativeRenderer, namespace) {
2120
+ const ns = nativeRenderer.getNameSpace(type, namespace);
2121
+ return createChildChain(children, nativeRenderer, ns);
2096
2122
  }
2097
2123
  function createElement(nativeRenderer, atom, parentComponent, context) {
2098
2124
  const { namespace, jsxNode } = atom;
@@ -2101,7 +2127,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2101
2127
  let bindingRefs;
2102
2128
  for (const key in props) {
2103
2129
  if (key === 'children') {
2104
- atom.child = createElementChildren(jsxNode.type, props.children, namespace);
2130
+ atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
2105
2131
  continue;
2106
2132
  }
2107
2133
  if (key === 'class') {
@@ -2192,7 +2218,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2192
2218
  }, (key, value) => {
2193
2219
  if (key === 'children') {
2194
2220
  updatedChildren = true;
2195
- newAtom.child = createElementChildren(newVNode.type, value, isSvg);
2221
+ newAtom.child = createElementChildren(newVNode.type, value, nativeRenderer, isSvg);
2196
2222
  buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
2197
2223
  return;
2198
2224
  }
@@ -2221,7 +2247,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2221
2247
  }, (key, newValue, oldValue) => {
2222
2248
  if (key === 'children') {
2223
2249
  updatedChildren = true;
2224
- newAtom.child = createElementChildren(newVNode.type, newValue, isSvg);
2250
+ newAtom.child = createElementChildren(newVNode.type, newValue, nativeRenderer, isSvg);
2225
2251
  if (!newAtom.child) {
2226
2252
  cleanElementChildren(oldAtom, nativeRenderer);
2227
2253
  }
@@ -2265,7 +2291,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2265
2291
  });
2266
2292
  if (!updatedChildren) {
2267
2293
  newAtom.child = oldAtom.child;
2268
- reuseElementChildrenView(nativeRenderer, newAtom);
2294
+ // reuseElementChildrenView(nativeRenderer, newAtom, context)
2269
2295
  }
2270
2296
  applyRefs(unBindRefs, nativeNode, false);
2271
2297
  applyRefs(bindRefs, nativeNode, true);
@@ -2482,29 +2508,120 @@ function shallowReactive(raw) {
2482
2508
  return proxy;
2483
2509
  }
2484
2510
 
2485
- function watch(trigger, callback) {
2486
- let prevFn;
2487
- const dep = new Dep(() => {
2488
- pushDepContext(dep);
2489
- const newValue = trigger();
2490
- popDepContext();
2491
- if (newValue === oldValue) {
2511
+ /**
2512
+ * 组件状态管理器
2513
+ * @param state 初始状态
2514
+ * @example
2515
+ * ```tsx
2516
+ * function App() {
2517
+ * // 初始化状态
2518
+ * const state = createSignal(1)
2519
+ *
2520
+ * return () => {
2521
+ * <div>
2522
+ * <div>当前值为:{state()}</div>
2523
+ * <div>
2524
+ * <button type="button" onClick={() => {
2525
+ * // 当点击时更新状态
2526
+ * state.set(state() + 1)
2527
+ * }
2528
+ * }>updateState</button>
2529
+ * </div>
2530
+ * </div>
2531
+ * }
2532
+ * }
2533
+ */
2534
+ function createSignal(state) {
2535
+ const subscribers = new Set();
2536
+ function signal() {
2537
+ const listener = getDepContext();
2538
+ if (listener && !subscribers.has(listener)) {
2539
+ listener.destroyCallbacks.push(() => {
2540
+ subscribers.delete(listener);
2541
+ });
2542
+ subscribers.add(listener);
2543
+ }
2544
+ return state;
2545
+ }
2546
+ signal.set = function (newValue) {
2547
+ if (newValue === state) {
2492
2548
  return;
2493
2549
  }
2550
+ state = newValue;
2551
+ const listeners = Array.from(subscribers);
2552
+ listeners.forEach(listener => listener.effect());
2553
+ };
2554
+ return signal;
2555
+ }
2556
+
2557
+ /**
2558
+ * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
2559
+ * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
2560
+ *
2561
+ * @param fn
2562
+ * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
2563
+ */
2564
+ function createDerived(fn, isContinue) {
2565
+ let isStop = false;
2566
+ function canListen(value) {
2567
+ if (isContinue) {
2568
+ const b = isContinue(value);
2569
+ if (b === false) {
2570
+ listener.destroy();
2571
+ return false;
2572
+ }
2573
+ }
2574
+ return true;
2575
+ }
2576
+ const listener = new Dep(() => {
2577
+ if (isStop) {
2578
+ return;
2579
+ }
2580
+ isStop = true;
2581
+ listener.destroy();
2582
+ pushDepContext(listener);
2583
+ const value = fn();
2584
+ popDepContext();
2585
+ signal.set(value);
2586
+ canListen(value);
2587
+ isStop = false;
2588
+ });
2589
+ pushDepContext(listener);
2590
+ const value = fn();
2591
+ const signal = createSignal(value);
2592
+ popDepContext();
2593
+ isStop = false;
2594
+ if (canListen(value)) {
2595
+ registryComponentDestroyCallback(() => listener.destroy());
2596
+ }
2597
+ return signal;
2598
+ }
2599
+
2600
+ /* eslint-enable max-len*/
2601
+ function createEffect(deps, callback) {
2602
+ let prevFn;
2603
+ const isArray = Array.isArray(deps);
2604
+ const effect = new Dep(function () {
2494
2605
  if (prevFn) {
2495
2606
  prevFn();
2496
2607
  }
2608
+ const newValue = isArray ? deps.map(fn => fn()) : deps();
2497
2609
  prevFn = callback(newValue, oldValue);
2498
2610
  oldValue = newValue;
2499
2611
  });
2500
- pushDepContext(dep);
2501
- let oldValue = trigger();
2612
+ pushDepContext(effect);
2613
+ let oldValue = isArray ? deps.map(fn => fn()) : deps();
2502
2614
  popDepContext();
2503
- dep.destroyCallbacks.push(() => {
2504
- prevFn === null || prevFn === void 0 ? void 0 : prevFn();
2505
- });
2615
+ let isUnWatch = false;
2506
2616
  function unWatch() {
2507
- dep.destroy();
2617
+ if (isUnWatch) {
2618
+ return;
2619
+ }
2620
+ isUnWatch = true;
2621
+ if (prevFn) {
2622
+ prevFn();
2623
+ }
2624
+ effect.destroy();
2508
2625
  }
2509
2626
  registryComponentDestroyCallback(unWatch);
2510
2627
  return unWatch;
@@ -2514,7 +2631,6 @@ exports.ArrayReactiveHandler = ArrayReactiveHandler;
2514
2631
  exports.Component = Component;
2515
2632
  exports.Dep = Dep;
2516
2633
  exports.DynamicRef = DynamicRef;
2517
- exports.ElementNamespaceMap = ElementNamespaceMap;
2518
2634
  exports.ForwardRef = ForwardRef;
2519
2635
  exports.Fragment = Fragment;
2520
2636
  exports.Inject = Inject;
@@ -2540,9 +2656,13 @@ exports.Type = Type;
2540
2656
  exports.comparePropsWithCallbacks = comparePropsWithCallbacks;
2541
2657
  exports.computed = computed;
2542
2658
  exports.createContext = createContext;
2659
+ exports.createContextProvider = createContextProvider;
2660
+ exports.createDerived = createDerived;
2543
2661
  exports.createDynamicRef = createDynamicRef;
2662
+ exports.createEffect = createEffect;
2544
2663
  exports.createRef = createRef;
2545
2664
  exports.createRenderer = createRenderer;
2665
+ exports.createSignal = createSignal;
2546
2666
  exports.defaultArrayReactiveHandler = defaultArrayReactiveHandler;
2547
2667
  exports.defaultMapReactiveHandler = defaultMapReactiveHandler;
2548
2668
  exports.defaultObjectReactiveHandler = defaultObjectReactiveHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "2.0.0-alpha.4",
3
+ "version": "2.0.0-alpha.6",
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": "3cb6bb4b345ccda0679c35a39c8f17211b0c6826",
53
+ "gitHead": "287516a11d9fddbe9f38c341e06d1b7256cfe7ac",
54
54
  "dependencies": {
55
55
  "reflect-metadata": "^0.2.2"
56
56
  }