Skip to content

Vue Router

todo 进阶

官网:https://router.vuejs.org/zh/introduction.html

默认情况下,所有路由是不区分大小写的。
例如,路由 /users 将匹配 /users/users//Users/
strict 和 sensitive 这两个 config 用于这个问题。

路径排名工具:https://paths.esm.dev/?p=AAMeJSyAwR4UbFDAFxAcAGAIJXMAAA..#

部署相关:https://router.vuejs.org/zh/guide/essentials/history-mode.html#服务器配置示例

嵌套路由

/ 开头的 path 将被视为根路径

js
{
  path: '/admin',
  children: [
    { path: '', component: AdminOverview }, // /admin/ 将匹配这个
    { path: 'users', component: AdminUserList },
    { path: 'users/:id', component: AdminUserDetails },
  ],
},

导航

声明式 <router-link :to="...">
编程式 router.push(...)

push 可以返回 replace 只是替换,不可以返回,声明式为 <router-link :to="..." replace>

js
// 向前移动一条记录,与 router.forward() 相同
router.go(1);

// 返回一条记录,与 router.back() 相同
router.go(-1);
js
router.push("/users/eduardo");

router.push({ path: "/users/eduardo" });

// /users/eduardo
router.push({ name: "user", params: { username: "eduardo" } });

// 结果是 /register?plan=private
router.push({ path: "/register", query: { plan: "private" } });

// 结果是 /about#team
router.push({ path: "/about", hash: "#team" });

如果提供了 path,params 会被忽略,params 不能与 path 一起使用!!!

params 是 /:id 中的 :id, 可以理解为 name 专属的。

params 类型应是 string 或 number,其他会被字符串化。

可选参数,你可以提供一个空字符串("")或 null 。

js
router.push({ name: "user", params: { username } }); // -> /user/eduardo

router.push({ path: "/user", params: { username } }); // -> /user

路由 props

组件中使用 $route 或 useRoute() 会与 vue-router 紧密耦合,可以通过 props 解耦

js
const routes = [{ path: "/user/:id", component: User, props: true }];
vue
<template>
  <div>User {{ id }}</div>
</template>

<script setup>
defineProps({
  id: String,
});
</script>

这样,id 就通过 props 的形式传入组件中

当 routes 中的 props 为 true 时,route.params 将被设置为组件的 props。

props 的方式很多,这里在记录一下 函数模式。

js
const routes = [
  {
    path: "/search",
    component: SearchUser,
    props: (route) => ({ query: route.query.q }),
  },
];

命名视图 / 多 router-view

html
<router-view class="view left-sidebar" name="LeftSidebar" />
<router-view class="view main-content" />
<router-view class="view right-sidebar" name="RightSidebar" />

需要注意 ,routes 中的 components 带 s

js
{
  path: '/',
  components: {
    default: Home,
    // LeftSidebar: LeftSidebar 的缩写
    LeftSidebar,
    // 它们与 `<router-view>` 上的 `name` 属性匹配
    RightSidebar,
  },
},

动态路由

js
{ path: '/users/:id', component: User }
html
<div>User {{ $route.params.id }}</div>

/users/johnny 导航到 /users/jolyne 时,组件不会销毁在创建,而是复用,所以生命周期并不会完整执行。
此时可以通过 watch 进行监听 或 导航守卫 onBeforeRouteUpdate

js
import { useRoute, onBeforeRouteUpdate } from "vue-router";

const route = useRoute();
watch(
  () => route.params.id,
  (newId, oldId) => {
    // 对路由变化做出响应...
  }
);

onBeforeRouteUpdate(async (to, from) => {
  // 对路由变化做出响应...
  userData.value = await fetchUser(to.params.id);
});

高级匹配规则

js
// /:orderId -> 仅匹配数字
{ path: '/:orderId(\\d+)' },

// /:productName -> 匹配其他任何内容
{ path: '/:productName' },

命名路由

命名路由是可选的,也是必须是唯一的

js
{
  path: '/user/:username',
  name: 'profile',
  component: User
}
js
router.push({ name: "profile", params: { username: "erina" } });
// 结果为 /user/erina

重定向

js
const routes = [{ path: "/home", redirect: "/" }];

redirect 也可以是方法

js
{
  path: '/search/:searchText',
  redirect: to => {
    // 方法接收目标路由作为参数
    // return 重定向的字符串路径/路径对象
    return { path: '/search', query: { q: to.params.searchText } }
  },
},

别名

用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /

js
const routes = [{ path: "/", component: Homepage, alias: "/home" }];

404

js
const routes = [
  // js 中通过 route.params.pathMatch 获取
  { path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },
  // 将匹配以 `/user-` 开头的
  // js 中通过 route.params.pathMatch 获取
  { path: "/user-:afterUser(.*)", component: UserGeneric },
];