无需正则表达式,如何为SvelteKit菜单标记当前URL的CSS类?
解决SvelteKit菜单路由高亮的误匹配问题(无需正则)
问题场景
我在SvelteKit项目中用以下菜单数组渲染导航:
const menu = [ { name: "players", url: "/players" }, { name: "team", url: "/players/team" }, { name: "player detail", url: "/players/[id]" }, // id为字符串参数 { name: "player's team coach detail", url: "/players/[id]/coach" }, // 更多菜单项... ];
原本用class:current="{page.url.pathname.startsWith(url)}"判断当前路由,但会把/players的所有子路由(比如/players/team、/players/123/coach)都错误标记为current,需要在不用正则的前提下实现精确匹配。
解决方案:路径分段对比法
核心思路是把当前路径和菜单路由都拆分成路径段,对比分段的长度和每一段的匹配情况——动态路由段(如[id])直接视为匹配,静态段必须完全相等。
代码实现:
<script> import { page } from '$app/stores'; const menu = [ { name: "players", url: "/players" }, { name: "team", url: "/players/team" }, { name: "player detail", url: "/players/[id]" }, { name: "player's team coach detail", url: "/players/[id]/coach" }, ]; // 辅助函数:拆分路径为非空分段数组 const splitPath = (path) => path.split('/').filter(seg => seg.trim()); </script> {#each menu as item} {#const currentPathSegments = splitPath($page.url.pathname)} {#const menuPathSegments = splitPath(item.url)} {#const isCurrent = // 首先保证路径分段数量一致 currentPathSegments.length === menuPathSegments.length && // 逐个对比每一段 menuPathSegments.every((seg, idx) => { // 如果是动态路由参数段,直接匹配成功 if (seg.startsWith('[') && seg.endsWith(']')) return true; // 静态段必须完全相等 return seg === currentPathSegments[idx]; }) } <a href={item.url} class:current={isCurrent} aria-current={isCurrent ? 'page' : undefined} > {item.name} </a> {/each}
为什么这个方法有效?
- 静态路由如
/players只会匹配分段长度为1且唯一分段是players的路径,不会匹配/players/team(分段长度为2)。 - 动态路由如
/players/[id]会匹配所有/players/xxx格式的路径,同时不会匹配更长的路径(比如/players/xxx/coach,分段长度为3)。 - 完全不用正则,逻辑清晰,兼容性好,其他JS框架可以直接复用这个思路。
内容的提问来源于stack exchange,提问作者Fred Hors
相关产品推荐
相关产品推荐

