Move components.ts into many SFC files
This commit is contained in:
110
packages/core/src/components/lifecycle.ts
Executable file
110
packages/core/src/components/lifecycle.ts
Executable file
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
inject,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
onScopeDispose,
|
||||
watch,
|
||||
type InjectionKey,
|
||||
} from "vue";
|
||||
import { nativeRouterKey } from "../runtime";
|
||||
import type { NativeRouterRuntime, NativeViewLifecycle } from "../types";
|
||||
|
||||
export const nativeViewLifecycleKey: InjectionKey<NativeViewLifecycle> = Symbol(
|
||||
"native-view-lifecycle",
|
||||
);
|
||||
|
||||
export function useNativeRouter() {
|
||||
const runtime = inject<NativeRouterRuntime>(nativeRouterKey);
|
||||
if (!runtime)
|
||||
throw new Error(
|
||||
"Native Vue Router is not installed. Call app.use(nativeRouter).",
|
||||
);
|
||||
return runtime;
|
||||
}
|
||||
|
||||
export function useNativeViewLifecycle() {
|
||||
const lifecycle = inject<NativeViewLifecycle>(nativeViewLifecycleKey);
|
||||
if (!lifecycle)
|
||||
throw new Error(
|
||||
"Native view lifecycle APIs must be used inside NativeRouterView.",
|
||||
);
|
||||
return lifecycle;
|
||||
}
|
||||
|
||||
type NativeViewHook = () => void;
|
||||
|
||||
function onNativeViewState(
|
||||
source: Readonly<{ value: boolean }>,
|
||||
entering: boolean,
|
||||
hook: NativeViewHook,
|
||||
) {
|
||||
onMounted(() => {
|
||||
if (entering && source.value) hook();
|
||||
});
|
||||
watch(
|
||||
() => source.value,
|
||||
(value, previous) => {
|
||||
if (value === entering && previous !== entering) hook();
|
||||
},
|
||||
{ flush: "sync" },
|
||||
);
|
||||
}
|
||||
|
||||
export function onNativeViewActivate(hook: NativeViewHook) {
|
||||
onNativeViewState(useNativeViewLifecycle().isActive, true, hook);
|
||||
}
|
||||
|
||||
export function onNativeViewDeactivate(hook: NativeViewHook) {
|
||||
onNativeViewState(useNativeViewLifecycle().isActive, false, hook);
|
||||
}
|
||||
|
||||
export function onNativeViewShow(hook: NativeViewHook) {
|
||||
onNativeViewState(useNativeViewLifecycle().isVisible, true, hook);
|
||||
}
|
||||
|
||||
export function onNativeViewHide(hook: NativeViewHook) {
|
||||
onNativeViewState(useNativeViewLifecycle().isVisible, false, hook);
|
||||
}
|
||||
|
||||
export function onNativeViewEvict(
|
||||
hook: (reason: NativeViewLifecycle["evictionReason"]["value"]) => void,
|
||||
) {
|
||||
const lifecycle = useNativeViewLifecycle();
|
||||
onBeforeUnmount(() => {
|
||||
if (lifecycle.status.value === "evicted")
|
||||
hook(lifecycle.evictionReason.value);
|
||||
});
|
||||
}
|
||||
|
||||
function useNativeViewEffect(
|
||||
source: Readonly<{ value: boolean }>,
|
||||
effect: () => void | (() => void),
|
||||
) {
|
||||
let cleanup: void | (() => void);
|
||||
const stopEffect = () => {
|
||||
cleanup?.();
|
||||
cleanup = undefined;
|
||||
};
|
||||
const stopWatch = watch(
|
||||
() => source.value,
|
||||
(enabled) => {
|
||||
stopEffect();
|
||||
if (enabled) cleanup = effect();
|
||||
},
|
||||
{ immediate: true, flush: "sync" },
|
||||
);
|
||||
onScopeDispose(() => {
|
||||
stopWatch();
|
||||
stopEffect();
|
||||
});
|
||||
}
|
||||
|
||||
/** Runs an effect only while this route is the semantically active route. */
|
||||
export function useNativeViewActiveEffect(effect: () => void | (() => void)) {
|
||||
useNativeViewEffect(useNativeViewLifecycle().isActive, effect);
|
||||
}
|
||||
|
||||
/** Runs an effect while this route is active or participating in a transition. */
|
||||
export function useNativeViewVisibleEffect(effect: () => void | (() => void)) {
|
||||
useNativeViewEffect(useNativeViewLifecycle().isVisible, effect);
|
||||
}
|
||||
Reference in New Issue
Block a user