Svelte使用svelte-spa-router如何按跳转场景自定义页面过渡效果
Svelte SPA 路由场景化过渡解决方案
1. 实现路由历史记录追踪
首先解决svelte-spa-router无法直接获取前序路由的问题,通过监听全局$location store维护路由历史栈:
// src/stores/routeHistory.js import { writable } from 'svelte/store'; import { location } from 'svelte-spa-router'; const createRouteHistory = () => { const { subscribe, set, update } = writable([]); // 监听路由变化更新历史栈 location.subscribe((newPath) => { update(history => { // 最多保留2层历史,仅需前序和当前路由即可满足匹配需求 return [...history.slice(-1), newPath]; }); }); return { subscribe, // 便捷获取前序、当前路由的方法 getPrevCurrent: () => { let hist; subscribe(h => hist = h)(); return [hist[hist.length - 2] || '', hist[hist.length - 1] || '']; } } } export const routeHistory = createRouteHistory();
2. 声明式配置过渡规则
把所有场景对应的过渡效果统一存到配置表中,避免硬编码判断逻辑,后续UX调整仅需修改配置即可:
// src/config/transitionRules.js import { fade, fly } from 'svelte/transition'; // 规则格式:[来源路由前缀, 目标路由前缀] : { 入场过渡, 退场过渡 } export const transitionRules = new Map([ [['/b1', '/'], { out: (node) => fade(node, { duration: 0 }) }], [['/b1', '/c1'], { out: (node) => fly(node, { x: -500, duration: 400 }) }], [['/b1', '/b2'], { out: (node) => fade(node, { duration: 400 }) }], // 其他规则按需扩展,支持通配符匹配全场景 [['*', '/'], { in: (node) => fade(node, { duration: 0 }) }], ]);
3. 动态匹配过渡效果
在路由外层容器统一处理过渡逻辑,根据当前路由对自动匹配对应的过渡效果,无需在每个页面组件单独配置:
<!-- src/App.svelte --> <script> import Router from 'svelte-spa-router'; import { routeHistory } from './stores/routeHistory'; import { transitionRules } from './config/transitionRules'; import Home from './pages/Home.svelte'; import B1 from './pages/B1.svelte'; import B2 from './pages/B2.svelte'; import C1 from './pages/C1.svelte'; const routes = { '/': Home, '/b1': B1, '/b2': B2, '/c1': C1 }; let currentTransition = { in: null, out: null }; // 监听路由历史变化,自动匹配过渡规则 $: if ($routeHistory.length >= 2) { const [prev, current] = $routeHistory.slice(-2); currentTransition = getTransition(prev, current); } function getTransition(from, to) { // 优先匹配完全符合的规则 for (const [[fromRule, toRule], trans] of transitionRules) { const fromMatch = fromRule === '*' || from.startsWith(fromRule); const toMatch = toRule === '*' || to.startsWith(toRule); if (fromMatch && toMatch) return trans; } // 兜底默认过渡效果 return { in: (node) => fade(node, { duration: 300 }), out: (node) => fade(node, { duration: 300 }) } } </script> <main> {#key $location} <div in:={currentTransition.in} out:={currentTransition.out}> <Router {routes} /> </div> {/key} </main> <style> main { position: relative; width: 100vw; height: 100vh; overflow: hidden; } main > div { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } </style>
方案优势
- 所有过渡规则集中管理,UX调整无需修改业务组件代码
- 支持通配符规则,同主题页面可批量配置过渡效果
- 过渡逻辑完全和业务解耦,不会产生面条式判断代码
- 无需修改现有页面组件,对现有业务侵入性极低
内容的提问来源于stack exchange,提问作者Gabriel Glenn
相关产品推荐
相关产品推荐

