@lazycatcloud/vue-router-stack
v0.0.4
Published
Page stack, caching, transitions, and lifecycle utilities built on vue-router.
Downloads
43
Readme
@lazycatcloud/vue-router-stack
基于 Vue 3 和 vue-router 的页面栈路由库。它保留 vue-router 的路由定义和导航能力,同时提供类似移动端页面栈的 DOM 缓存、转场、页面生命周期和调试面板。
当前版本适合浏览器端应用使用,暂不处理 SSR、手势返回识别、每个 tab 独立历史栈。
安装
pnpm add @lazycatcloud/vue-router-stack vue vue-router入口处引入样式:
import "@lazycatcloud/vue-router-stack/style.css";基础使用
创建 router 时使用 createStackRouter,其余路由写法保持 vue-router 风格。
import {
createStackRouter,
createWebHistory,
RouterView,
} from "@lazycatcloud/vue-router-stack";
export const router = createStackRouter({
history: createWebHistory(),
transition: "slide",
transitionDuration: 240,
routes: [
{
path: "/",
component: HomePage,
},
{
path: "/album",
component: RouterView,
children: [
{ path: "detail", component: AlbumDetail },
{ path: "map", component: AlbumMap },
],
},
],
});应用入口和普通 vue-router 一样:
import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router";
createApp(App).use(router).mount("#app");页面出口不要直接使用普通 <router-view>,使用 RouterOutlet:
<script setup lang="ts">
import { RouterOutlet } from "@lazycatcloud/vue-router-stack";
</script>
<template>
<RouterOutlet />
</template>页面组件根节点使用 RouterPage:
<script setup lang="ts">
import { RouterPage } from "@lazycatcloud/vue-router-stack";
</script>
<template>
<RouterPage>
<h1>Album Detail</h1>
</RouterPage>
</template>导航 API
在组件里使用 useStackRouter():
import { useStackRouter } from "@lazycatcloud/vue-router-stack";
const stackRouter = useStackRouter();
stackRouter.push("/album/detail");
stackRouter.replace("/album/detail");
stackRouter.back();
stackRouter.forward();
stackRouter.popTo("/album/detail");
stackRouter.resetRoot("/");单次导航可以控制方向、动画、时长和缓动:
stackRouter.push("/search/result", {
transition: "fade",
});
stackRouter.push("/timeline", {
direction: "none",
});
stackRouter.push("/detail", {
transition: "sheet",
duration: 300,
easing: "ease-out",
});direction: "none" 和 direction: "root" 会强制不播放转场,适合 tab 切换和清栈回首页。
转场动画
内置动画:
slidefadescalenone
可以通过 defineStackTransition 注册自定义动画:
import { createStackRouter, defineStackTransition } from "@lazycatcloud/vue-router-stack";
export const router = createStackRouter({
history: createWebHistory(),
transition: "slide",
transitions: {
sheet: defineStackTransition(({ direction }) => ({
entering:
direction === "back"
? [{ transform: "translateY(-8%)" }, { transform: "translateY(0)" }]
: [{ transform: "translateY(100%)" }, { transform: "translateY(0)" }],
leaving:
direction === "back"
? [{ transform: "translateY(0)" }, { transform: "translateY(100%)" }]
: [{ transform: "translateY(0)" }, { transform: "translateY(-8%)" }],
})),
},
routes,
});返回时会优先使用离开页面进入时记录的动画。例如用 sheet 打开详情页,返回时会按 sheet 收起。
转场决策
shouldTransition 用于业务侧决定本次导航是否播放动画。库只提供上下文,不内置 iOS 或具体设备判断。
const isIOS =
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
export const router = createStackRouter({
history: createWebHistory(),
shouldTransition(ctx) {
if (isIOS && ctx.source === "external") return false;
return ctx.defaultResult;
},
routes,
});ctx.source 有两个值:
stack:由stackRouter.push/back/popTo/resetRoot等库 API 触发。external:由浏览器 history 或系统手势等外部来源触发。
页面生命周期
页面被栈缓存时不会频繁卸载,可以使用页面生命周期处理进入和离开:
import {
onPageDidEnter,
onPageDidLeave,
onPageWillEnter,
onPageWillLeave,
} from "@lazycatcloud/vue-router-stack";
onPageWillEnter(() => {});
onPageDidEnter(() => {});
onPageWillLeave(() => {});
onPageDidLeave(() => {});触发顺序保持为:
onPageWillEnteronPageWillLeave- 转场动画
onPageDidLeaveonPageDidEnter
缓存策略
默认页面会缓存,返回时复用旧实例并保留滚动位置和组件状态。
可以在路由 meta 中关闭某个页面的缓存:
{
path: "/search/result",
component: SearchResult,
meta: {
stackCache: false,
},
}也可以使用嵌套写法:
{
path: "/search/result",
component: SearchResult,
meta: {
stack: {
cache: false,
},
},
}通过 maxStackSize 限制最大缓存栈长度:
createStackRouter({
history: createWebHistory(),
maxStackSize: 30,
routes,
});调试面板
开发时可以挂载 StackRouterDebugPanel 查看当前栈、缓存、转场和导航来源:
<script setup lang="ts">
import { StackRouterDebugPanel } from "@lazycatcloud/vue-router-stack";
</script>
<template>
<RouterView />
<StackRouterDebugPanel />
</template>Demo
本仓库内置 PC 和 Mobile 两个 demo:
- PC:左侧侧边栏 + 右侧内容区
- Mobile:顶部内容区 + 底部栏切换
pnpm install
pnpm dev验证
pnpm run type-check
pnpm test
pnpm run build