@viewfly/core 1.0.4 → 1.0.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.
- package/bundles/index.d.ts +62 -63
- package/bundles/index.esm.js +161 -201
- package/bundles/index.js +162 -200
- package/package.json +2 -2
package/bundles/index.d.ts
CHANGED
|
@@ -260,6 +260,7 @@ declare namespace JSX {
|
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
declare function getSetupContext(need?: boolean): Component;
|
|
263
264
|
type ClassNames = string | Record<string, unknown> | false | null | undefined | ClassNames[];
|
|
264
265
|
interface ComponentInstance<P> {
|
|
265
266
|
$portalHost?: NativeNode;
|
|
@@ -295,9 +296,9 @@ declare class Component extends ReflectiveInjector {
|
|
|
295
296
|
private propsChangedDestroyCallbacks?;
|
|
296
297
|
protected _dirty: boolean;
|
|
297
298
|
protected _changed: boolean;
|
|
298
|
-
private unWatch?;
|
|
299
299
|
private isFirstRendering;
|
|
300
300
|
private refs;
|
|
301
|
+
private listener;
|
|
301
302
|
constructor(parentComponent: Injector | null, type: ComponentSetup, props: Props, key?: Key | undefined);
|
|
302
303
|
markAsDirtied(): void;
|
|
303
304
|
markAsChanged(changedComponent?: Component): void;
|
|
@@ -412,13 +413,52 @@ declare class StaticRef<T> extends DynamicRef<T> {
|
|
|
412
413
|
constructor();
|
|
413
414
|
}
|
|
414
415
|
declare function createRef<T, U = ExtractInstanceType<T>>(): StaticRef<U>;
|
|
415
|
-
declare const depsKey: unique symbol;
|
|
416
416
|
/**
|
|
417
|
-
*
|
|
417
|
+
* 给组件添加注解
|
|
418
|
+
* @param annotation
|
|
419
|
+
* @param componentSetup
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* export customScope = new Scope('scopeName')
|
|
423
|
+
* export const App = withAnnotation({
|
|
424
|
+
* scope: customScope,
|
|
425
|
+
* providers: [
|
|
426
|
+
* ExampleService
|
|
427
|
+
* ]
|
|
428
|
+
* }, function(props: Props) {
|
|
429
|
+
* return () => {
|
|
430
|
+
* return <div>...</div>
|
|
431
|
+
* }
|
|
432
|
+
* })
|
|
418
433
|
* ```
|
|
419
434
|
*/
|
|
435
|
+
declare function withAnnotation<T extends ComponentSetup>(annotation: ComponentAnnotation, componentSetup: T): T;
|
|
436
|
+
/**
|
|
437
|
+
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
438
|
+
*/
|
|
439
|
+
declare function inject<T extends Type<any> | AbstractType<any> | InjectionToken<any>, U = never>(token: T, notFoundValue?: U, flags?: InjectFlags): ExtractValueType<T> | U;
|
|
440
|
+
/**
|
|
441
|
+
* 获取当前组件实例
|
|
442
|
+
*/
|
|
443
|
+
declare function getCurrentInstance(): Component;
|
|
444
|
+
|
|
445
|
+
declare function withMemo<T extends Props = Props>(canUseMemo: ComponentInstance<T>['$useMemo'], render: () => JSXNode): ComponentInstance<T>;
|
|
446
|
+
|
|
447
|
+
declare function createRenderer(component: Component, nativeRenderer: NativeRenderer): (host: NativeNode) => void;
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
451
|
+
*/
|
|
452
|
+
declare class RootComponent extends Component {
|
|
453
|
+
private refresh;
|
|
454
|
+
constructor(parentInjector: Injector | null, factory: ComponentSetup, refresh: () => void);
|
|
455
|
+
markAsChanged(changedComponent?: Component): void;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* 组件状态实例,直接调用可以获取最新的状态,通过 set 方法可以更新状态
|
|
460
|
+
*/
|
|
420
461
|
interface Signal<T> {
|
|
421
|
-
$isSignal: true;
|
|
422
462
|
/**
|
|
423
463
|
* 直接调用一个 Signal 实例,可以获取最新状态
|
|
424
464
|
*/
|
|
@@ -428,7 +468,6 @@ interface Signal<T> {
|
|
|
428
468
|
* @param newState
|
|
429
469
|
*/
|
|
430
470
|
set(newState: T): void;
|
|
431
|
-
[depsKey]: Set<LifeCycleCallback>;
|
|
432
471
|
}
|
|
433
472
|
/**
|
|
434
473
|
* 组件状态管理器
|
|
@@ -456,14 +495,15 @@ interface Signal<T> {
|
|
|
456
495
|
declare function createSignal<T>(state: T): Signal<T>;
|
|
457
496
|
/**
|
|
458
497
|
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
459
|
-
* 并在你获取
|
|
498
|
+
* 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
460
499
|
*
|
|
461
|
-
* @param
|
|
500
|
+
* @param fn
|
|
462
501
|
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
463
502
|
*/
|
|
464
|
-
declare function
|
|
465
|
-
|
|
466
|
-
|
|
503
|
+
declare function computed<T>(fn: () => T, isContinue?: (data: T) => unknown): Signal<T>;
|
|
504
|
+
declare const createDerived: typeof computed;
|
|
505
|
+
interface WatchCallback<T> {
|
|
506
|
+
(newValue: T, oldValue: T): void | (() => void);
|
|
467
507
|
}
|
|
468
508
|
/**
|
|
469
509
|
* 监听状态变化,当任意一个状态发生变更时,触发回调。
|
|
@@ -472,58 +512,17 @@ interface WatchCallback<T, U> {
|
|
|
472
512
|
* @param deps 依赖的状态 Signal,可以是一个 Signal,只可以一个数包含 Signal 的数组,或者是一个求值函数
|
|
473
513
|
* @param callback 状态变更后的回调函数
|
|
474
514
|
*/
|
|
475
|
-
declare function watch<T>(deps: Signal<T>, callback: WatchCallback<T
|
|
476
|
-
declare function watch<T>(deps: [Signal<T>], callback: WatchCallback<[T]
|
|
477
|
-
declare function watch<T, T1>(deps: [Signal<T>, Signal<T1>], callback: WatchCallback<[T, T1]
|
|
478
|
-
declare function watch<T, T1, T2>(deps: [Signal<T>, Signal<T1>, Signal<T2>], callback: WatchCallback<[T, T1, T2]
|
|
479
|
-
declare function watch<T, T1, T2, T3>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>], callback: WatchCallback<[T, T1, T2, T3]
|
|
480
|
-
declare function watch<T, T1, T2, T3, T4>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>], callback: WatchCallback<[T, T1, T2, T3, T4]
|
|
481
|
-
declare function watch<T, T1, T2, T3, T4, T5>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>], callback: WatchCallback<[T, T1, T2, T3, T4, T5]
|
|
482
|
-
declare function watch<T, T1, T2, T3, T4, T5, T6>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>, Signal<T6>], callback: WatchCallback<[T, T1, T2, T3, T4, T5, T6]
|
|
483
|
-
declare function watch<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: WatchCallback<[T, T1, T2, T3, T4, T5, T6, T7]
|
|
484
|
-
declare function watch<T>(deps: () => T, callback: WatchCallback<T
|
|
485
|
-
declare function watch<T = any>(deps: Signal<any>[], callback: WatchCallback<T[]
|
|
486
|
-
/**
|
|
487
|
-
* 给组件添加注解
|
|
488
|
-
* @param annotation
|
|
489
|
-
* @param componentSetup
|
|
490
|
-
* @example
|
|
491
|
-
* ```ts
|
|
492
|
-
* export customScope = new Scope('scopeName')
|
|
493
|
-
* export const App = withAnnotation({
|
|
494
|
-
* scope: customScope,
|
|
495
|
-
* providers: [
|
|
496
|
-
* ExampleService
|
|
497
|
-
* ]
|
|
498
|
-
* }, function(props: Props) {
|
|
499
|
-
* return () => {
|
|
500
|
-
* return <div>...</div>
|
|
501
|
-
* }
|
|
502
|
-
* })
|
|
503
|
-
* ```
|
|
504
|
-
*/
|
|
505
|
-
declare function withAnnotation<T extends ComponentSetup>(annotation: ComponentAnnotation, componentSetup: T): T;
|
|
506
|
-
/**
|
|
507
|
-
* 通过组件上下文获取 IoC 容器内数据的勾子方法
|
|
508
|
-
*/
|
|
509
|
-
declare function inject<T extends Type<any> | AbstractType<any> | InjectionToken<any>, U = never>(token: T, notFoundValue?: U, flags?: InjectFlags): ExtractValueType<T> | U;
|
|
510
|
-
/**
|
|
511
|
-
* 获取当前组件实例
|
|
512
|
-
*/
|
|
513
|
-
declare function getCurrentInstance(): Component;
|
|
514
|
-
|
|
515
|
-
declare function withMemo<T extends Props = Props>(canUseMemo: ComponentInstance<T>['$useMemo'], render: () => JSXNode): ComponentInstance<T>;
|
|
516
|
-
|
|
517
|
-
declare function createRenderer(component: Component, nativeRenderer: NativeRenderer): (host: NativeNode) => void;
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Viewfly 根组件,用于实现组件状态更新事件通知
|
|
521
|
-
*/
|
|
522
|
-
declare class RootComponent extends Component {
|
|
523
|
-
private refresh;
|
|
524
|
-
constructor(parentInjector: Injector | null, factory: ComponentSetup, refresh: () => void);
|
|
525
|
-
markAsChanged(changedComponent?: Component): void;
|
|
526
|
-
}
|
|
515
|
+
declare function watch<T>(deps: Signal<T>, callback: WatchCallback<T>): () => void;
|
|
516
|
+
declare function watch<T>(deps: [Signal<T>], callback: WatchCallback<[T]>): () => void;
|
|
517
|
+
declare function watch<T, T1>(deps: [Signal<T>, Signal<T1>], callback: WatchCallback<[T, T1]>): () => void;
|
|
518
|
+
declare function watch<T, T1, T2>(deps: [Signal<T>, Signal<T1>, Signal<T2>], callback: WatchCallback<[T, T1, T2]>): () => void;
|
|
519
|
+
declare function watch<T, T1, T2, T3>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>], callback: WatchCallback<[T, T1, T2, T3]>): () => void;
|
|
520
|
+
declare function watch<T, T1, T2, T3, T4>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>], callback: WatchCallback<[T, T1, T2, T3, T4]>): () => void;
|
|
521
|
+
declare function watch<T, T1, T2, T3, T4, T5>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>], callback: WatchCallback<[T, T1, T2, T3, T4, T5]>): () => void;
|
|
522
|
+
declare function watch<T, T1, T2, T3, T4, T5, T6>(deps: [Signal<T>, Signal<T1>, Signal<T2>, Signal<T3>, Signal<T4>, Signal<T5>, Signal<T6>], callback: WatchCallback<[T, T1, T2, T3, T4, T5, T6]>): () => void;
|
|
523
|
+
declare function watch<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: WatchCallback<[T, T1, T2, T3, T4, T5, T6, T7]>): () => void;
|
|
524
|
+
declare function watch<T>(deps: () => T, callback: WatchCallback<T>): () => void;
|
|
525
|
+
declare function watch<T = any>(deps: Signal<any>[], callback: WatchCallback<T[]>): () => void;
|
|
527
526
|
|
|
528
527
|
declare const TextAtomType: unique symbol;
|
|
529
528
|
declare const ElementAtomType: unique symbol;
|
|
@@ -596,4 +595,4 @@ interface Module {
|
|
|
596
595
|
}
|
|
597
596
|
declare function viewfly<T extends NativeNode>(config: Config): Application<T>;
|
|
598
597
|
|
|
599
|
-
export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentView, type Config, type ConstructorProvider, Context, type ContextProps, DynamicRef, 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, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type PropsChangedCallback, type ProvideScope, type Provider, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, type Signal, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, type WatchCallback, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
|
598
|
+
export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentView, type Config, type ConstructorProvider, Context, type ContextProps, DynamicRef, 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, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type PropsChangedCallback, type ProvideScope, type Provider, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, type Signal, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, type WatchCallback, computed, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, getSetupContext, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
package/bundles/index.esm.js
CHANGED
|
@@ -570,23 +570,6 @@ function getObjectChanges(newProps, oldProps) {
|
|
|
570
570
|
}
|
|
571
571
|
return changes;
|
|
572
572
|
}
|
|
573
|
-
function getArrayChanges(left, right) {
|
|
574
|
-
const changes = {
|
|
575
|
-
add: [],
|
|
576
|
-
remove: []
|
|
577
|
-
};
|
|
578
|
-
for (const i of left) {
|
|
579
|
-
if (!right.includes(i)) {
|
|
580
|
-
changes.remove.push(i);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
for (const i of right) {
|
|
584
|
-
if (!left.includes(i)) {
|
|
585
|
-
changes.add.push(i);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return changes;
|
|
589
|
-
}
|
|
590
573
|
function classToString(config) {
|
|
591
574
|
if (typeof config === 'string') {
|
|
592
575
|
return config;
|
|
@@ -635,8 +618,28 @@ const TextAtomType = Symbol('Text');
|
|
|
635
618
|
const ElementAtomType = Symbol('Element');
|
|
636
619
|
const ComponentAtomType = Symbol('Component');
|
|
637
620
|
|
|
621
|
+
class Listener {
|
|
622
|
+
constructor(effect) {
|
|
623
|
+
this.effect = effect;
|
|
624
|
+
this.destroyCallbacks = [];
|
|
625
|
+
}
|
|
626
|
+
destroy() {
|
|
627
|
+
this.destroyCallbacks.forEach(fn => fn());
|
|
628
|
+
this.destroyCallbacks = [];
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
const listeners = [];
|
|
632
|
+
function getCurrentListener() {
|
|
633
|
+
return listeners.at(-1);
|
|
634
|
+
}
|
|
635
|
+
function pushListener(listener) {
|
|
636
|
+
listeners.push(listener);
|
|
637
|
+
}
|
|
638
|
+
function popListener() {
|
|
639
|
+
listeners.pop();
|
|
640
|
+
}
|
|
641
|
+
|
|
638
642
|
const componentSetupStack = [];
|
|
639
|
-
const signalDepsStack = [];
|
|
640
643
|
const componentErrorFn = makeError('component');
|
|
641
644
|
function getSetupContext(need = true) {
|
|
642
645
|
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
@@ -646,9 +649,6 @@ function getSetupContext(need = true) {
|
|
|
646
649
|
}
|
|
647
650
|
return current;
|
|
648
651
|
}
|
|
649
|
-
function getSignalDepsContext() {
|
|
650
|
-
return signalDepsStack[signalDepsStack.length - 1];
|
|
651
|
-
}
|
|
652
652
|
/**
|
|
653
653
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
654
654
|
*/
|
|
@@ -675,6 +675,9 @@ class Component extends ReflectiveInjector {
|
|
|
675
675
|
this._changed = true;
|
|
676
676
|
this.isFirstRendering = true;
|
|
677
677
|
this.refs = null;
|
|
678
|
+
this.listener = new Listener(() => {
|
|
679
|
+
this.markAsDirtied();
|
|
680
|
+
});
|
|
678
681
|
}
|
|
679
682
|
markAsDirtied() {
|
|
680
683
|
this._dirty = true;
|
|
@@ -728,12 +731,9 @@ class Component extends ReflectiveInjector {
|
|
|
728
731
|
}
|
|
729
732
|
isSetup = false;
|
|
730
733
|
componentSetupStack.pop();
|
|
731
|
-
|
|
734
|
+
pushListener(this.listener);
|
|
732
735
|
const template = this.instance.$render();
|
|
733
|
-
|
|
734
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
735
|
-
this.markAsDirtied();
|
|
736
|
-
});
|
|
736
|
+
popListener();
|
|
737
737
|
update(template, this.instance.$portalHost);
|
|
738
738
|
this.rendered();
|
|
739
739
|
}
|
|
@@ -772,13 +772,10 @@ class Component extends ReflectiveInjector {
|
|
|
772
772
|
return;
|
|
773
773
|
}
|
|
774
774
|
}
|
|
775
|
-
this.
|
|
776
|
-
|
|
775
|
+
this.listener.destroy();
|
|
776
|
+
pushListener(this.listener);
|
|
777
777
|
const template = this.instance.$render();
|
|
778
|
-
|
|
779
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
780
|
-
this.markAsDirtied();
|
|
781
|
-
});
|
|
778
|
+
popListener();
|
|
782
779
|
updateChildren(template);
|
|
783
780
|
this.rendered();
|
|
784
781
|
}
|
|
@@ -788,7 +785,7 @@ class Component extends ReflectiveInjector {
|
|
|
788
785
|
}
|
|
789
786
|
destroy() {
|
|
790
787
|
var _a, _b, _c;
|
|
791
|
-
this.
|
|
788
|
+
this.listener.destroy();
|
|
792
789
|
(_a = this.updatedDestroyCallbacks) === null || _a === void 0 ? void 0 : _a.forEach(fn => {
|
|
793
790
|
fn();
|
|
794
791
|
});
|
|
@@ -1050,173 +1047,6 @@ class StaticRef extends DynamicRef {
|
|
|
1050
1047
|
function createRef() {
|
|
1051
1048
|
return new StaticRef();
|
|
1052
1049
|
}
|
|
1053
|
-
const depsKey = Symbol('deps');
|
|
1054
|
-
/**
|
|
1055
|
-
* 组件状态管理器
|
|
1056
|
-
* @param state 初始状态
|
|
1057
|
-
* @example
|
|
1058
|
-
* ```tsx
|
|
1059
|
-
* function App() {
|
|
1060
|
-
* // 初始化状态
|
|
1061
|
-
* const state = createSignal(1)
|
|
1062
|
-
*
|
|
1063
|
-
* return () => {
|
|
1064
|
-
* <div>
|
|
1065
|
-
* <div>当前值为:{state()}</div>
|
|
1066
|
-
* <div>
|
|
1067
|
-
* <button type="button" onClick={() => {
|
|
1068
|
-
* // 当点击时更新状态
|
|
1069
|
-
* state.set(state() + 1)
|
|
1070
|
-
* }
|
|
1071
|
-
* }>updateState</button>
|
|
1072
|
-
* </div>
|
|
1073
|
-
* </div>
|
|
1074
|
-
* }
|
|
1075
|
-
* }
|
|
1076
|
-
*/
|
|
1077
|
-
function createSignal(state) {
|
|
1078
|
-
function signal() {
|
|
1079
|
-
const depsContext = getSignalDepsContext();
|
|
1080
|
-
if (depsContext) {
|
|
1081
|
-
depsContext.push(signal);
|
|
1082
|
-
}
|
|
1083
|
-
return state;
|
|
1084
|
-
}
|
|
1085
|
-
signal.$isSignal = true;
|
|
1086
|
-
signal.set = function (newState) {
|
|
1087
|
-
if (newState === state) {
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
state = newState;
|
|
1091
|
-
const depCallbacks = Array.from(signal[depsKey]);
|
|
1092
|
-
for (const fn of depCallbacks) {
|
|
1093
|
-
// 回调中可能会对依赖做出修改,故需先缓存起来
|
|
1094
|
-
fn();
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
//
|
|
1098
|
-
// signal.toString = function () {
|
|
1099
|
-
// return String(state)
|
|
1100
|
-
// }
|
|
1101
|
-
//
|
|
1102
|
-
// signal.valueOf = function () {
|
|
1103
|
-
// return state
|
|
1104
|
-
// }
|
|
1105
|
-
signal[depsKey] = new Set();
|
|
1106
|
-
return signal;
|
|
1107
|
-
}
|
|
1108
|
-
function invokeDepFn(fn) {
|
|
1109
|
-
const deps = [];
|
|
1110
|
-
signalDepsStack.push(deps);
|
|
1111
|
-
const data = fn();
|
|
1112
|
-
signalDepsStack.pop();
|
|
1113
|
-
return {
|
|
1114
|
-
deps: Array.from(new Set(deps)),
|
|
1115
|
-
data
|
|
1116
|
-
};
|
|
1117
|
-
}
|
|
1118
|
-
function listen(model, deps, callback, isContinue) {
|
|
1119
|
-
let isStop = false;
|
|
1120
|
-
const nextListen = () => {
|
|
1121
|
-
if (isStop) {
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
isStop = true;
|
|
1125
|
-
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
1126
|
-
model.set(nextData);
|
|
1127
|
-
if (typeof isContinue === 'function' && isContinue(nextData) === false) {
|
|
1128
|
-
unListen();
|
|
1129
|
-
return;
|
|
1130
|
-
}
|
|
1131
|
-
const changes = getArrayChanges(deps, nextDeps);
|
|
1132
|
-
deps = deps.filter(i => {
|
|
1133
|
-
const has = changes.remove.includes(i);
|
|
1134
|
-
if (has) {
|
|
1135
|
-
i[depsKey].delete(nextListen);
|
|
1136
|
-
return false;
|
|
1137
|
-
}
|
|
1138
|
-
return true;
|
|
1139
|
-
});
|
|
1140
|
-
for (const s of changes.add) {
|
|
1141
|
-
s[depsKey].add(nextListen);
|
|
1142
|
-
}
|
|
1143
|
-
deps.push(...changes.add);
|
|
1144
|
-
isStop = false;
|
|
1145
|
-
};
|
|
1146
|
-
const unListen = () => {
|
|
1147
|
-
for (const s of deps) {
|
|
1148
|
-
s[depsKey].delete(nextListen);
|
|
1149
|
-
}
|
|
1150
|
-
};
|
|
1151
|
-
for (const s of deps) {
|
|
1152
|
-
s[depsKey].add(nextListen);
|
|
1153
|
-
}
|
|
1154
|
-
return unListen;
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1158
|
-
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1159
|
-
*
|
|
1160
|
-
* @param callback
|
|
1161
|
-
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1162
|
-
*/
|
|
1163
|
-
function createDerived(callback, isContinue) {
|
|
1164
|
-
const { data, deps } = invokeDepFn(callback);
|
|
1165
|
-
const signal = createSignal(data);
|
|
1166
|
-
const component = getSetupContext(false);
|
|
1167
|
-
const unListen = listen(signal, deps, callback, isContinue);
|
|
1168
|
-
if (component) {
|
|
1169
|
-
if (!component.unmountedCallbacks) {
|
|
1170
|
-
component.unmountedCallbacks = [];
|
|
1171
|
-
}
|
|
1172
|
-
component.unmountedCallbacks.push(() => {
|
|
1173
|
-
unListen();
|
|
1174
|
-
});
|
|
1175
|
-
}
|
|
1176
|
-
return signal;
|
|
1177
|
-
}
|
|
1178
|
-
/* eslint-enable max-len*/
|
|
1179
|
-
function watch(deps, callback) {
|
|
1180
|
-
if (typeof deps === 'function' && !deps.$isSignal) {
|
|
1181
|
-
deps = createDerived(deps);
|
|
1182
|
-
}
|
|
1183
|
-
const signals = Array.isArray(deps) ? deps : [deps];
|
|
1184
|
-
let oldValues = signals.map(s => s());
|
|
1185
|
-
let prevCleanup;
|
|
1186
|
-
function effectCallback() {
|
|
1187
|
-
if (typeof prevCleanup === 'function') {
|
|
1188
|
-
prevCleanup();
|
|
1189
|
-
}
|
|
1190
|
-
const newValues = signals.map(s => s());
|
|
1191
|
-
prevCleanup = Array.isArray(deps) ? callback(newValues, oldValues) : callback(newValues[0], oldValues[0]);
|
|
1192
|
-
oldValues = newValues;
|
|
1193
|
-
}
|
|
1194
|
-
for (const dep of signals) {
|
|
1195
|
-
dep[depsKey].add(effectCallback);
|
|
1196
|
-
}
|
|
1197
|
-
const component = getSetupContext(false);
|
|
1198
|
-
let isClean = false;
|
|
1199
|
-
const destroyFn = () => {
|
|
1200
|
-
if (isClean) {
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
|
-
isClean = true;
|
|
1204
|
-
if (component === null || component === void 0 ? void 0 : component.unmountedCallbacks) {
|
|
1205
|
-
const index = component.unmountedCallbacks.indexOf(destroyFn);
|
|
1206
|
-
component.unmountedCallbacks.splice(index, 1);
|
|
1207
|
-
}
|
|
1208
|
-
for (const dep of signals) {
|
|
1209
|
-
dep[depsKey].delete(effectCallback);
|
|
1210
|
-
}
|
|
1211
|
-
};
|
|
1212
|
-
if (component) {
|
|
1213
|
-
if (!component.unmountedCallbacks) {
|
|
1214
|
-
component.unmountedCallbacks = [];
|
|
1215
|
-
}
|
|
1216
|
-
component.unmountedCallbacks.push(destroyFn);
|
|
1217
|
-
}
|
|
1218
|
-
return destroyFn;
|
|
1219
|
-
}
|
|
1220
1050
|
/**
|
|
1221
1051
|
* 给组件添加注解
|
|
1222
1052
|
* @param annotation
|
|
@@ -1741,6 +1571,9 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1741
1571
|
if (!newAtom.child) {
|
|
1742
1572
|
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1743
1573
|
}
|
|
1574
|
+
else if (!oldAtom.child) {
|
|
1575
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
1576
|
+
}
|
|
1744
1577
|
else {
|
|
1745
1578
|
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
1746
1579
|
}
|
|
@@ -1841,6 +1674,133 @@ class RootComponent extends Component {
|
|
|
1841
1674
|
}
|
|
1842
1675
|
}
|
|
1843
1676
|
|
|
1677
|
+
/**
|
|
1678
|
+
* 组件状态管理器
|
|
1679
|
+
* @param state 初始状态
|
|
1680
|
+
* @example
|
|
1681
|
+
* ```tsx
|
|
1682
|
+
* function App() {
|
|
1683
|
+
* // 初始化状态
|
|
1684
|
+
* const state = createSignal(1)
|
|
1685
|
+
*
|
|
1686
|
+
* return () => {
|
|
1687
|
+
* <div>
|
|
1688
|
+
* <div>当前值为:{state()}</div>
|
|
1689
|
+
* <div>
|
|
1690
|
+
* <button type="button" onClick={() => {
|
|
1691
|
+
* // 当点击时更新状态
|
|
1692
|
+
* state.set(state() + 1)
|
|
1693
|
+
* }
|
|
1694
|
+
* }>updateState</button>
|
|
1695
|
+
* </div>
|
|
1696
|
+
* </div>
|
|
1697
|
+
* }
|
|
1698
|
+
* }
|
|
1699
|
+
*/
|
|
1700
|
+
function createSignal(state) {
|
|
1701
|
+
const subscribers = new Set();
|
|
1702
|
+
function signal() {
|
|
1703
|
+
const listener = getCurrentListener();
|
|
1704
|
+
if (listener) {
|
|
1705
|
+
listener.destroyCallbacks.push(() => {
|
|
1706
|
+
subscribers.delete(listener);
|
|
1707
|
+
});
|
|
1708
|
+
subscribers.add(listener);
|
|
1709
|
+
}
|
|
1710
|
+
return state;
|
|
1711
|
+
}
|
|
1712
|
+
signal.set = function (newValue) {
|
|
1713
|
+
if (newValue === state) {
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
state = newValue;
|
|
1717
|
+
const listeners = Array.from(subscribers);
|
|
1718
|
+
listeners.forEach(listener => listener.effect());
|
|
1719
|
+
};
|
|
1720
|
+
return signal;
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1724
|
+
* 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1725
|
+
*
|
|
1726
|
+
* @param fn
|
|
1727
|
+
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1728
|
+
*/
|
|
1729
|
+
function computed(fn, isContinue) {
|
|
1730
|
+
let isStop = false;
|
|
1731
|
+
function canListen(value) {
|
|
1732
|
+
if (isContinue) {
|
|
1733
|
+
const b = isContinue(value);
|
|
1734
|
+
if (b === false) {
|
|
1735
|
+
listener.destroy();
|
|
1736
|
+
return false;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
return true;
|
|
1740
|
+
}
|
|
1741
|
+
const listener = new Listener(() => {
|
|
1742
|
+
if (isStop) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
isStop = true;
|
|
1746
|
+
listener.destroy();
|
|
1747
|
+
pushListener(listener);
|
|
1748
|
+
const value = fn();
|
|
1749
|
+
popListener();
|
|
1750
|
+
signal.set(value);
|
|
1751
|
+
canListen(value);
|
|
1752
|
+
isStop = false;
|
|
1753
|
+
});
|
|
1754
|
+
pushListener(listener);
|
|
1755
|
+
const value = fn();
|
|
1756
|
+
const signal = createSignal(value);
|
|
1757
|
+
popListener();
|
|
1758
|
+
isStop = false;
|
|
1759
|
+
if (canListen(value)) {
|
|
1760
|
+
registryComponentDestroyCallback(() => listener.destroy());
|
|
1761
|
+
}
|
|
1762
|
+
return signal;
|
|
1763
|
+
}
|
|
1764
|
+
const createDerived = computed;
|
|
1765
|
+
/* eslint-enable max-len*/
|
|
1766
|
+
function watch(deps, callback) {
|
|
1767
|
+
let prevFn;
|
|
1768
|
+
const isArray = Array.isArray(deps);
|
|
1769
|
+
const effect = new Listener(function () {
|
|
1770
|
+
if (prevFn) {
|
|
1771
|
+
prevFn();
|
|
1772
|
+
}
|
|
1773
|
+
const newValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1774
|
+
prevFn = callback(newValue, oldValue);
|
|
1775
|
+
oldValue = newValue;
|
|
1776
|
+
});
|
|
1777
|
+
pushListener(effect);
|
|
1778
|
+
let oldValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1779
|
+
popListener();
|
|
1780
|
+
let isUnWatch = false;
|
|
1781
|
+
function unWatch() {
|
|
1782
|
+
if (isUnWatch) {
|
|
1783
|
+
return;
|
|
1784
|
+
}
|
|
1785
|
+
isUnWatch = true;
|
|
1786
|
+
if (prevFn) {
|
|
1787
|
+
prevFn();
|
|
1788
|
+
}
|
|
1789
|
+
effect.destroy();
|
|
1790
|
+
}
|
|
1791
|
+
registryComponentDestroyCallback(unWatch);
|
|
1792
|
+
return unWatch;
|
|
1793
|
+
}
|
|
1794
|
+
function registryComponentDestroyCallback(fn) {
|
|
1795
|
+
const component = getSetupContext(false);
|
|
1796
|
+
if (component) {
|
|
1797
|
+
if (!component.unmountedCallbacks) {
|
|
1798
|
+
component.unmountedCallbacks = [];
|
|
1799
|
+
}
|
|
1800
|
+
component.unmountedCallbacks.push(fn);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1844
1804
|
const viewflyErrorFn = makeError('Viewfly');
|
|
1845
1805
|
function viewfly(config) {
|
|
1846
1806
|
const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
|
|
@@ -1928,4 +1888,4 @@ function viewfly(config) {
|
|
|
1928
1888
|
return app;
|
|
1929
1889
|
}
|
|
1930
1890
|
|
|
1931
|
-
export { Component, Context, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
|
1891
|
+
export { Component, Context, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, computed, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, getSetupContext, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
package/bundles/index.js
CHANGED
|
@@ -572,23 +572,6 @@ function getObjectChanges(newProps, oldProps) {
|
|
|
572
572
|
}
|
|
573
573
|
return changes;
|
|
574
574
|
}
|
|
575
|
-
function getArrayChanges(left, right) {
|
|
576
|
-
const changes = {
|
|
577
|
-
add: [],
|
|
578
|
-
remove: []
|
|
579
|
-
};
|
|
580
|
-
for (const i of left) {
|
|
581
|
-
if (!right.includes(i)) {
|
|
582
|
-
changes.remove.push(i);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
for (const i of right) {
|
|
586
|
-
if (!left.includes(i)) {
|
|
587
|
-
changes.add.push(i);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
return changes;
|
|
591
|
-
}
|
|
592
575
|
function classToString(config) {
|
|
593
576
|
if (typeof config === 'string') {
|
|
594
577
|
return config;
|
|
@@ -637,8 +620,28 @@ const TextAtomType = Symbol('Text');
|
|
|
637
620
|
const ElementAtomType = Symbol('Element');
|
|
638
621
|
const ComponentAtomType = Symbol('Component');
|
|
639
622
|
|
|
623
|
+
class Listener {
|
|
624
|
+
constructor(effect) {
|
|
625
|
+
this.effect = effect;
|
|
626
|
+
this.destroyCallbacks = [];
|
|
627
|
+
}
|
|
628
|
+
destroy() {
|
|
629
|
+
this.destroyCallbacks.forEach(fn => fn());
|
|
630
|
+
this.destroyCallbacks = [];
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const listeners = [];
|
|
634
|
+
function getCurrentListener() {
|
|
635
|
+
return listeners.at(-1);
|
|
636
|
+
}
|
|
637
|
+
function pushListener(listener) {
|
|
638
|
+
listeners.push(listener);
|
|
639
|
+
}
|
|
640
|
+
function popListener() {
|
|
641
|
+
listeners.pop();
|
|
642
|
+
}
|
|
643
|
+
|
|
640
644
|
const componentSetupStack = [];
|
|
641
|
-
const signalDepsStack = [];
|
|
642
645
|
const componentErrorFn = makeError('component');
|
|
643
646
|
function getSetupContext(need = true) {
|
|
644
647
|
const current = componentSetupStack[componentSetupStack.length - 1];
|
|
@@ -648,9 +651,6 @@ function getSetupContext(need = true) {
|
|
|
648
651
|
}
|
|
649
652
|
return current;
|
|
650
653
|
}
|
|
651
|
-
function getSignalDepsContext() {
|
|
652
|
-
return signalDepsStack[signalDepsStack.length - 1];
|
|
653
|
-
}
|
|
654
654
|
/**
|
|
655
655
|
* Viewfly 组件管理类,用于管理组件的生命周期,上下文等
|
|
656
656
|
*/
|
|
@@ -677,6 +677,9 @@ class Component extends ReflectiveInjector {
|
|
|
677
677
|
this._changed = true;
|
|
678
678
|
this.isFirstRendering = true;
|
|
679
679
|
this.refs = null;
|
|
680
|
+
this.listener = new Listener(() => {
|
|
681
|
+
this.markAsDirtied();
|
|
682
|
+
});
|
|
680
683
|
}
|
|
681
684
|
markAsDirtied() {
|
|
682
685
|
this._dirty = true;
|
|
@@ -730,12 +733,9 @@ class Component extends ReflectiveInjector {
|
|
|
730
733
|
}
|
|
731
734
|
isSetup = false;
|
|
732
735
|
componentSetupStack.pop();
|
|
733
|
-
|
|
736
|
+
pushListener(this.listener);
|
|
734
737
|
const template = this.instance.$render();
|
|
735
|
-
|
|
736
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
737
|
-
this.markAsDirtied();
|
|
738
|
-
});
|
|
738
|
+
popListener();
|
|
739
739
|
update(template, this.instance.$portalHost);
|
|
740
740
|
this.rendered();
|
|
741
741
|
}
|
|
@@ -774,13 +774,10 @@ class Component extends ReflectiveInjector {
|
|
|
774
774
|
return;
|
|
775
775
|
}
|
|
776
776
|
}
|
|
777
|
-
this.
|
|
778
|
-
|
|
777
|
+
this.listener.destroy();
|
|
778
|
+
pushListener(this.listener);
|
|
779
779
|
const template = this.instance.$render();
|
|
780
|
-
|
|
781
|
-
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
782
|
-
this.markAsDirtied();
|
|
783
|
-
});
|
|
780
|
+
popListener();
|
|
784
781
|
updateChildren(template);
|
|
785
782
|
this.rendered();
|
|
786
783
|
}
|
|
@@ -790,7 +787,7 @@ class Component extends ReflectiveInjector {
|
|
|
790
787
|
}
|
|
791
788
|
destroy() {
|
|
792
789
|
var _a, _b, _c;
|
|
793
|
-
this.
|
|
790
|
+
this.listener.destroy();
|
|
794
791
|
(_a = this.updatedDestroyCallbacks) === null || _a === void 0 ? void 0 : _a.forEach(fn => {
|
|
795
792
|
fn();
|
|
796
793
|
});
|
|
@@ -1052,173 +1049,6 @@ class StaticRef extends DynamicRef {
|
|
|
1052
1049
|
function createRef() {
|
|
1053
1050
|
return new StaticRef();
|
|
1054
1051
|
}
|
|
1055
|
-
const depsKey = Symbol('deps');
|
|
1056
|
-
/**
|
|
1057
|
-
* 组件状态管理器
|
|
1058
|
-
* @param state 初始状态
|
|
1059
|
-
* @example
|
|
1060
|
-
* ```tsx
|
|
1061
|
-
* function App() {
|
|
1062
|
-
* // 初始化状态
|
|
1063
|
-
* const state = createSignal(1)
|
|
1064
|
-
*
|
|
1065
|
-
* return () => {
|
|
1066
|
-
* <div>
|
|
1067
|
-
* <div>当前值为:{state()}</div>
|
|
1068
|
-
* <div>
|
|
1069
|
-
* <button type="button" onClick={() => {
|
|
1070
|
-
* // 当点击时更新状态
|
|
1071
|
-
* state.set(state() + 1)
|
|
1072
|
-
* }
|
|
1073
|
-
* }>updateState</button>
|
|
1074
|
-
* </div>
|
|
1075
|
-
* </div>
|
|
1076
|
-
* }
|
|
1077
|
-
* }
|
|
1078
|
-
*/
|
|
1079
|
-
function createSignal(state) {
|
|
1080
|
-
function signal() {
|
|
1081
|
-
const depsContext = getSignalDepsContext();
|
|
1082
|
-
if (depsContext) {
|
|
1083
|
-
depsContext.push(signal);
|
|
1084
|
-
}
|
|
1085
|
-
return state;
|
|
1086
|
-
}
|
|
1087
|
-
signal.$isSignal = true;
|
|
1088
|
-
signal.set = function (newState) {
|
|
1089
|
-
if (newState === state) {
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
state = newState;
|
|
1093
|
-
const depCallbacks = Array.from(signal[depsKey]);
|
|
1094
|
-
for (const fn of depCallbacks) {
|
|
1095
|
-
// 回调中可能会对依赖做出修改,故需先缓存起来
|
|
1096
|
-
fn();
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
//
|
|
1100
|
-
// signal.toString = function () {
|
|
1101
|
-
// return String(state)
|
|
1102
|
-
// }
|
|
1103
|
-
//
|
|
1104
|
-
// signal.valueOf = function () {
|
|
1105
|
-
// return state
|
|
1106
|
-
// }
|
|
1107
|
-
signal[depsKey] = new Set();
|
|
1108
|
-
return signal;
|
|
1109
|
-
}
|
|
1110
|
-
function invokeDepFn(fn) {
|
|
1111
|
-
const deps = [];
|
|
1112
|
-
signalDepsStack.push(deps);
|
|
1113
|
-
const data = fn();
|
|
1114
|
-
signalDepsStack.pop();
|
|
1115
|
-
return {
|
|
1116
|
-
deps: Array.from(new Set(deps)),
|
|
1117
|
-
data
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
function listen(model, deps, callback, isContinue) {
|
|
1121
|
-
let isStop = false;
|
|
1122
|
-
const nextListen = () => {
|
|
1123
|
-
if (isStop) {
|
|
1124
|
-
return;
|
|
1125
|
-
}
|
|
1126
|
-
isStop = true;
|
|
1127
|
-
const { data: nextData, deps: nextDeps } = invokeDepFn(callback);
|
|
1128
|
-
model.set(nextData);
|
|
1129
|
-
if (typeof isContinue === 'function' && isContinue(nextData) === false) {
|
|
1130
|
-
unListen();
|
|
1131
|
-
return;
|
|
1132
|
-
}
|
|
1133
|
-
const changes = getArrayChanges(deps, nextDeps);
|
|
1134
|
-
deps = deps.filter(i => {
|
|
1135
|
-
const has = changes.remove.includes(i);
|
|
1136
|
-
if (has) {
|
|
1137
|
-
i[depsKey].delete(nextListen);
|
|
1138
|
-
return false;
|
|
1139
|
-
}
|
|
1140
|
-
return true;
|
|
1141
|
-
});
|
|
1142
|
-
for (const s of changes.add) {
|
|
1143
|
-
s[depsKey].add(nextListen);
|
|
1144
|
-
}
|
|
1145
|
-
deps.push(...changes.add);
|
|
1146
|
-
isStop = false;
|
|
1147
|
-
};
|
|
1148
|
-
const unListen = () => {
|
|
1149
|
-
for (const s of deps) {
|
|
1150
|
-
s[depsKey].delete(nextListen);
|
|
1151
|
-
}
|
|
1152
|
-
};
|
|
1153
|
-
for (const s of deps) {
|
|
1154
|
-
s[depsKey].add(nextListen);
|
|
1155
|
-
}
|
|
1156
|
-
return unListen;
|
|
1157
|
-
}
|
|
1158
|
-
/**
|
|
1159
|
-
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1160
|
-
* 并在你获取 useDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1161
|
-
*
|
|
1162
|
-
* @param callback
|
|
1163
|
-
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1164
|
-
*/
|
|
1165
|
-
function createDerived(callback, isContinue) {
|
|
1166
|
-
const { data, deps } = invokeDepFn(callback);
|
|
1167
|
-
const signal = createSignal(data);
|
|
1168
|
-
const component = getSetupContext(false);
|
|
1169
|
-
const unListen = listen(signal, deps, callback, isContinue);
|
|
1170
|
-
if (component) {
|
|
1171
|
-
if (!component.unmountedCallbacks) {
|
|
1172
|
-
component.unmountedCallbacks = [];
|
|
1173
|
-
}
|
|
1174
|
-
component.unmountedCallbacks.push(() => {
|
|
1175
|
-
unListen();
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
return signal;
|
|
1179
|
-
}
|
|
1180
|
-
/* eslint-enable max-len*/
|
|
1181
|
-
function watch(deps, callback) {
|
|
1182
|
-
if (typeof deps === 'function' && !deps.$isSignal) {
|
|
1183
|
-
deps = createDerived(deps);
|
|
1184
|
-
}
|
|
1185
|
-
const signals = Array.isArray(deps) ? deps : [deps];
|
|
1186
|
-
let oldValues = signals.map(s => s());
|
|
1187
|
-
let prevCleanup;
|
|
1188
|
-
function effectCallback() {
|
|
1189
|
-
if (typeof prevCleanup === 'function') {
|
|
1190
|
-
prevCleanup();
|
|
1191
|
-
}
|
|
1192
|
-
const newValues = signals.map(s => s());
|
|
1193
|
-
prevCleanup = Array.isArray(deps) ? callback(newValues, oldValues) : callback(newValues[0], oldValues[0]);
|
|
1194
|
-
oldValues = newValues;
|
|
1195
|
-
}
|
|
1196
|
-
for (const dep of signals) {
|
|
1197
|
-
dep[depsKey].add(effectCallback);
|
|
1198
|
-
}
|
|
1199
|
-
const component = getSetupContext(false);
|
|
1200
|
-
let isClean = false;
|
|
1201
|
-
const destroyFn = () => {
|
|
1202
|
-
if (isClean) {
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1205
|
-
isClean = true;
|
|
1206
|
-
if (component === null || component === void 0 ? void 0 : component.unmountedCallbacks) {
|
|
1207
|
-
const index = component.unmountedCallbacks.indexOf(destroyFn);
|
|
1208
|
-
component.unmountedCallbacks.splice(index, 1);
|
|
1209
|
-
}
|
|
1210
|
-
for (const dep of signals) {
|
|
1211
|
-
dep[depsKey].delete(effectCallback);
|
|
1212
|
-
}
|
|
1213
|
-
};
|
|
1214
|
-
if (component) {
|
|
1215
|
-
if (!component.unmountedCallbacks) {
|
|
1216
|
-
component.unmountedCallbacks = [];
|
|
1217
|
-
}
|
|
1218
|
-
component.unmountedCallbacks.push(destroyFn);
|
|
1219
|
-
}
|
|
1220
|
-
return destroyFn;
|
|
1221
|
-
}
|
|
1222
1052
|
/**
|
|
1223
1053
|
* 给组件添加注解
|
|
1224
1054
|
* @param annotation
|
|
@@ -1743,6 +1573,9 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1743
1573
|
if (!newAtom.child) {
|
|
1744
1574
|
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1745
1575
|
}
|
|
1576
|
+
else if (!oldAtom.child) {
|
|
1577
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
1578
|
+
}
|
|
1746
1579
|
else {
|
|
1747
1580
|
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
1748
1581
|
}
|
|
@@ -1843,6 +1676,133 @@ class RootComponent extends Component {
|
|
|
1843
1676
|
}
|
|
1844
1677
|
}
|
|
1845
1678
|
|
|
1679
|
+
/**
|
|
1680
|
+
* 组件状态管理器
|
|
1681
|
+
* @param state 初始状态
|
|
1682
|
+
* @example
|
|
1683
|
+
* ```tsx
|
|
1684
|
+
* function App() {
|
|
1685
|
+
* // 初始化状态
|
|
1686
|
+
* const state = createSignal(1)
|
|
1687
|
+
*
|
|
1688
|
+
* return () => {
|
|
1689
|
+
* <div>
|
|
1690
|
+
* <div>当前值为:{state()}</div>
|
|
1691
|
+
* <div>
|
|
1692
|
+
* <button type="button" onClick={() => {
|
|
1693
|
+
* // 当点击时更新状态
|
|
1694
|
+
* state.set(state() + 1)
|
|
1695
|
+
* }
|
|
1696
|
+
* }>updateState</button>
|
|
1697
|
+
* </div>
|
|
1698
|
+
* </div>
|
|
1699
|
+
* }
|
|
1700
|
+
* }
|
|
1701
|
+
*/
|
|
1702
|
+
function createSignal(state) {
|
|
1703
|
+
const subscribers = new Set();
|
|
1704
|
+
function signal() {
|
|
1705
|
+
const listener = getCurrentListener();
|
|
1706
|
+
if (listener) {
|
|
1707
|
+
listener.destroyCallbacks.push(() => {
|
|
1708
|
+
subscribers.delete(listener);
|
|
1709
|
+
});
|
|
1710
|
+
subscribers.add(listener);
|
|
1711
|
+
}
|
|
1712
|
+
return state;
|
|
1713
|
+
}
|
|
1714
|
+
signal.set = function (newValue) {
|
|
1715
|
+
if (newValue === state) {
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
state = newValue;
|
|
1719
|
+
const listeners = Array.from(subscribers);
|
|
1720
|
+
listeners.forEach(listener => listener.effect());
|
|
1721
|
+
};
|
|
1722
|
+
return signal;
|
|
1723
|
+
}
|
|
1724
|
+
/**
|
|
1725
|
+
* 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
|
|
1726
|
+
* 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
|
|
1727
|
+
*
|
|
1728
|
+
* @param fn
|
|
1729
|
+
* @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
|
|
1730
|
+
*/
|
|
1731
|
+
function computed(fn, isContinue) {
|
|
1732
|
+
let isStop = false;
|
|
1733
|
+
function canListen(value) {
|
|
1734
|
+
if (isContinue) {
|
|
1735
|
+
const b = isContinue(value);
|
|
1736
|
+
if (b === false) {
|
|
1737
|
+
listener.destroy();
|
|
1738
|
+
return false;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
return true;
|
|
1742
|
+
}
|
|
1743
|
+
const listener = new Listener(() => {
|
|
1744
|
+
if (isStop) {
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
isStop = true;
|
|
1748
|
+
listener.destroy();
|
|
1749
|
+
pushListener(listener);
|
|
1750
|
+
const value = fn();
|
|
1751
|
+
popListener();
|
|
1752
|
+
signal.set(value);
|
|
1753
|
+
canListen(value);
|
|
1754
|
+
isStop = false;
|
|
1755
|
+
});
|
|
1756
|
+
pushListener(listener);
|
|
1757
|
+
const value = fn();
|
|
1758
|
+
const signal = createSignal(value);
|
|
1759
|
+
popListener();
|
|
1760
|
+
isStop = false;
|
|
1761
|
+
if (canListen(value)) {
|
|
1762
|
+
registryComponentDestroyCallback(() => listener.destroy());
|
|
1763
|
+
}
|
|
1764
|
+
return signal;
|
|
1765
|
+
}
|
|
1766
|
+
const createDerived = computed;
|
|
1767
|
+
/* eslint-enable max-len*/
|
|
1768
|
+
function watch(deps, callback) {
|
|
1769
|
+
let prevFn;
|
|
1770
|
+
const isArray = Array.isArray(deps);
|
|
1771
|
+
const effect = new Listener(function () {
|
|
1772
|
+
if (prevFn) {
|
|
1773
|
+
prevFn();
|
|
1774
|
+
}
|
|
1775
|
+
const newValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1776
|
+
prevFn = callback(newValue, oldValue);
|
|
1777
|
+
oldValue = newValue;
|
|
1778
|
+
});
|
|
1779
|
+
pushListener(effect);
|
|
1780
|
+
let oldValue = isArray ? deps.map(fn => fn()) : deps();
|
|
1781
|
+
popListener();
|
|
1782
|
+
let isUnWatch = false;
|
|
1783
|
+
function unWatch() {
|
|
1784
|
+
if (isUnWatch) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
isUnWatch = true;
|
|
1788
|
+
if (prevFn) {
|
|
1789
|
+
prevFn();
|
|
1790
|
+
}
|
|
1791
|
+
effect.destroy();
|
|
1792
|
+
}
|
|
1793
|
+
registryComponentDestroyCallback(unWatch);
|
|
1794
|
+
return unWatch;
|
|
1795
|
+
}
|
|
1796
|
+
function registryComponentDestroyCallback(fn) {
|
|
1797
|
+
const component = getSetupContext(false);
|
|
1798
|
+
if (component) {
|
|
1799
|
+
if (!component.unmountedCallbacks) {
|
|
1800
|
+
component.unmountedCallbacks = [];
|
|
1801
|
+
}
|
|
1802
|
+
component.unmountedCallbacks.push(fn);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1846
1806
|
const viewflyErrorFn = makeError('Viewfly');
|
|
1847
1807
|
function viewfly(config) {
|
|
1848
1808
|
const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
|
|
@@ -1952,6 +1912,7 @@ exports.SkipSelf = SkipSelf;
|
|
|
1952
1912
|
exports.StaticRef = StaticRef;
|
|
1953
1913
|
exports.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
|
|
1954
1914
|
exports.Type = Type;
|
|
1915
|
+
exports.computed = computed;
|
|
1955
1916
|
exports.createDerived = createDerived;
|
|
1956
1917
|
exports.createDynamicRef = createDynamicRef;
|
|
1957
1918
|
exports.createRef = createRef;
|
|
@@ -1959,6 +1920,7 @@ exports.createRenderer = createRenderer;
|
|
|
1959
1920
|
exports.createSignal = createSignal;
|
|
1960
1921
|
exports.forwardRef = forwardRef;
|
|
1961
1922
|
exports.getCurrentInstance = getCurrentInstance;
|
|
1923
|
+
exports.getSetupContext = getSetupContext;
|
|
1962
1924
|
exports.inject = inject;
|
|
1963
1925
|
exports.jsx = jsx;
|
|
1964
1926
|
exports.jsxs = jsxs;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viewfly/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.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": "
|
|
53
|
+
"gitHead": "b66ca589f7662cd518fc2e5955b3e3ff9de83f94",
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"reflect-metadata": "^0.2.2"
|
|
56
56
|
}
|