Move components.ts into many SFC files

This commit is contained in:
2026-07-22 02:38:01 +00:00
parent 18baa96848
commit bfe364c57d
10 changed files with 814 additions and 760 deletions

View 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);
}