window.addEventListener('hashchange',function(){})监听浏览器左右箭头的变化window.addEventListener('popstate',function(){})监听浏览器左右箭头的变化// 命名的路由,并加上参数
router.push({ name: "user", params: { username: "eduardo" } });
// 带查询参数
router.push({ path: "/register", query: { plan: "private" } });
replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push(),所以导航后不会留下历史记录(浏览器不能通过左右箭头回退,快进)。使用场景:用户登录后不想保留登录页信息<router-link to="/abc" replace></router-link>
<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view main-content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/",
components: {
// 它们与 `<router-view>` 上的 `name` 属性匹配
// 放在对应的位置
default: () => import("./Home.vue"),
LeftSidebar: () => import("./LeftSidebar.vue"),
RightSidebar: () => import("./RightSidebar.vue")
}
}
]
});
守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
const router = createRouter({ ... })
router.beforeEach((to, from, next) => {
if (to.name !== "Login" && !isAuthenticated) next({ name: "Login" });
else next();
});
next() : 放行next('/login') : 中断当前路由去 login在 addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚 addRoutes()就立刻访问被添加的路由,然而此时 addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。
解决方法:next({...to,replace:true})
next({...to,replace:true}) :...to 如果 addRoutes 并未完成,路由守卫会重复执行去,直到 addRoutes 完成,找到对应的路由replace:true 在 to 执行的时候不允许用户点击回退,防止产生异常onBeforeRouteLeave((to, from) => {
const answer = window.confirm(
"Do you really want to leave? you have unsaved changes!"
);
// 取消导航并停留在同一页面上
if (!answer) return false;
});
const userData = ref();
onBeforeRouteUpdate(async (to, from) => {
//仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id);
}
});
const routes = [
{
path: '/posts',
component: PostsLayout,
children: [
{
path: 'new',
component: PostsNew,
// 只有经过身份验证的用户才能创建帖子
meta: { requiresAuth: true }
},
{
path: ':id',
component: PostsDetail
// 任何人都可以阅读文章
meta: { requiresAuth: false }
}
]
}
]
/posts/new 这个 URL 将会匹配父路由记录 (path: '/posts') 以及子路由记录 (path: 'new')。一个路由匹配到的所有路由记录会暴露为 $route 对象, Vue Router 提供了一个 $route.meta方法,它是一个非递归合并所有 meta 字段的方法。这意味着你可以简单地写router.beforeEach((to, from) => {
if (to.meta.requiresAuth && !auth.isLoggedIn()) {
// 此路由需要授权,请检查是否已登录
// 如果没有,则重定向到登录页面
return {
path: "/login",
// 保存我们所在的位置,以便以后再来
query: { redirect: to.fullPath }
};
}
});
RouteMeta 接口来输入 meta 字段:// typings.d.ts or router.ts
import "vue-router";
declare module "vue-router" {
interface RouteMeta {
// 是可选的
isAdmin?: boolean;
// 每个路由都必须声明
requiresAuth: boolean;
}
}
import { useRouter, useRoute } from "vue-router";
export default {
setup() {
const router = useRouter();
const route = useRoute();
function pushWithQuery(query) {
router.push({
name: "search",
query: {
...route.query
}
});
}
}
};
import { useRoute } from "vue-router";
import { ref, watch } from "vue";
export default {
setup() {
const route = useRoute();
const userData = ref();
// 当参数更改时获取用户信息
watch(
() => route.params.id,
async (newId) => {
userData.value = await fetchUser(newId);
}
);
}
};
所有的路由使用同一种过渡效果以下示例均搭配 animate.css,基于本站
transition 过渡组件
<router-view v-slot="{ Component }">
<transition enter-active-class="animate__animated animate__fadeIn">
<component :is="Component" />
</transition>
</router-view>
const routes = [
{
path: "/custom-transition",
component: PanelLeft,
meta: { transition: "animate__fadeIn" }
},
{
path: "/other-transition",
component: PanelRight,
meta: { transition: "animate__fadeInDown" }
}
];
<!-- router-view支持插槽,可以解出Component, route -->
<router-view v-slot="{ Component, route }">
<transition enter-active-class="animate__animated ${route.meta.transition}">
<component :is="Component" />
</transition>
</router-view>
<router-view v-slot="{ Component, route }">
<transition enter-active-class="animate__animated ${route.meta.transition}">
<component :is="Component" :key="route.path" />
</transition>
</router-view>
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
//如果当前页面向下滚动了300px,则下一个页面离顶部也是300px
return savedPosition;
// 如果滚动出现异常,尝试添加 behavior
// return { ...savedPosition, behavior: "smooth" };
} else {
return { top: 0, left: 0 };
}
}
});
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ left: 0, top: 0 });
}, 500);
});
}
});
router.addRoutes()添加路由。router.addRoute({ path: "/about", component: About });
router.addRoute(),这将有效地添加路由,就像通过 children 添加的一样:router.addRoute({ name: "admin", path: "/admin", component: Admin });
router.addRoute("admin", { path: "settings", component: AdminSettings });
router.addRoute({
name: "admin",
path: "/admin",
component: Admin,
children: [{ path: "settings", component: AdminSettings }]
});
router.addRoute({ path: "/about", name: "about", component: About });
// 这将会删除之前已经添加的路由,因为他们具有相同的名字且名字必须是唯一的
router.addRoute({ path: "/other", name: "about", component: Other });
const removeRoute = router.addRoute(routeRecord);
removeRoute(); // 删除路由如果存在的话
当路由没有名称时,这很有用。
router.addRoute({ path: "/about", name: "about", component: About });
// 删除路由
router.removeRoute("about");
Symbol 作为名字。
当路由被删除时,所有的别名和子路由也会被同时删除