vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
全局前置守卫
可以使用 router.beforeEach
注册一个全局前置守卫。
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
每个守卫方法接收两个参数:
可以返回的值如下:
false
: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。- 一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像调用
router.push(
) 一样,你可以设置诸如replace: true
或name: 'home'
之类的配置。当前的导航被中断,然后进行一个新的导航,就和from
一样。
示例:
在本示例中使用router.beforeEach作为拦截,使用mate设定部分路由必须经过验证。验证规则为判断cookie中auth值是否存在。对不符合条件的请求,转到/login上。
js/getCookie.js
获取指定cookie值,如果不存在,则返回null
function getCookie (name) {
const cookies = document.cookie.split('; ');
for (const cookie of cookies) {
const [cookieName, cookieValue] = cookie.split('=');
if (cookieName === name) {
return cookieValue;
}
}
return null; // 如果没有找到匹配的 Cookie,返回 null 或其他默认值
}
export {getCookie}
router/index.js
路由设定:
- / /user /login无需登录即可访问
- /user/list /user/detail 需要cookie中有指定值(模拟登录状态)才可访问
- 不能直接访问的跳转到Login
import { createRouter, createWebHashHistory } from 'vue-router'
import Root from '../views/RootView.vue'
import Users from '../views/usersview.vue'
import UserList from '../views/User/UserList.vue'
import UserDetail from '../views/User/UserDetail.vue'
import Login from '../views/LoginView.vue'
import { getCookie } from '../js/getCookie'
const routes = [
{
path: '/',
component: Root
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/user',
component: Users,
// meta:{
// LoginRequire:true
// },
children: [
{
path: 'list',
component: UserList,
meta: {
LoginRequire: true
}
},
{
path: 'detail/:userid',
component: UserDetail,
meta: {
LoginRequire: true
},
}
]
}
]
const myCookieValue = getCookie('auth');
const router = createRouter({
history: createWebHashHistory(),
routes
})
router.beforeEach((to, from, next) => {
if (to.name !== 'login' && !myCookieValue && to.meta.LoginRequire) {
console.log('jump to login')
next({
name: 'login',
query: {
from: from.fullPath
}
})
}
else {
next()
}
}
)
export default router
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
sendToAnalytics(to.fullPath)
})
它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
它们也反映了 navigation failures 作为第三个参数:
router.afterEach((to, from, failure) => {
if (!failure) sendToAnalytics(to.fullPath)
})
路由独享的守卫
你可以直接在路由配置上定义 beforeEnter
守卫:
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]
beforeEnter
守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。例如,从 /users/2 进入到 /users/3 或者从 /users/2#info 进入到 /users/2#projects。它们只有在 从一个不同的 路由导航时,才会被触发。
组件内的守卫
最后,你可以在路由组件内直接定义路由导航守卫(传递给路由配置的)
可用的配置 API
你可以为路由组件添加以下配置:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
}
在之前的文档中使用watch对相同组件内的路由切换进行处理,在这里可以使用beforeRouteUpdate
()进行同样操作。
对于组件式则使用onBeforeUpdate
来实现
// watch(() => route.params, async (newUserId) => {
// await fetchData(newUserId);
// });
onBeforeRouteUpdate(async(to,from)=>{
await fetchData(to.params.userid)
})
标签:Vue,users,08,守卫,Part,组件,router,导航,路由
From: https://blog.51cto.com/quietguoguo/7060425