导航守卫
官方解释:
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
全局守卫:
router.enterEach((to,from,next)>={
})
to: Route: 即将要进入的目标路由对象
对应参数
fullPath:"/foo" hash:"" matched:[] meta:{} name:null params: __proto__:Object path:"/foo" query:{}
from: Route: 当前导航正要离开的路由 (可以当成重定向使用)
ƒunction redirect(location) { return _this2.push(location); }
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
<template>
<div>
<h2>About</h2>
</div>
</template>
components/Dashboard.vue
<template>
<div>
<h2>Dashboard</h2>
<p>Yay you made it!</p>
</div>
</template>
components/login.vue
<template>
<div>
<h2>login</h2>
</div>
</template>
app.js
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) import About from './components/About.vue' import Dashboard from './components/Dashboard.vue' import Login from './components/Login.vue' const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ { path: '/about', component: About }, { path: '/dashboard', component: Dashboard }, { path: '/login', component: Login,name:'Login' } ] }) router.beforeEach((to, from, next) => { const islogin=false console.log(to.path) console.log(!islogin&&to.path=='/login') if(!islogin&&to.path=='/login'){ next(); }else{ from({path:'login'}) } }) var vm=new Vue({ router, template: ` <div id="app"> <h1>Navigation Guards</h1> <ul> <li><router-link to="/">/</router-link></li> <li><router-link to="/about">/about</router-link></li> <li><router-link to="/dashboard">/dashboard</router-link></li> <li><router-link to="/login">/dashboard</router-link></li> </ul> <router-view class="view"></router-view> </div>
`
}).$mount('#app')

上图实现的直接链接判断是否登入时,未登录的情况下直接跳转到登录页
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
举个例子
注意小组件如上面一个例子
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) import auth from './auth' import App from './components/App.vue' import About from './components/About.vue' import Dashboard from './components/Dashboard.vue' import Login from './components/Login.vue' function requireAuth (route, redirect, next) { if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: route.fullPath } }) } else { next() } } const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ { path: '/about', component: About, beforeEnter: function (to, from) { const login = false if (!login) {
alert('111') from('/login') } } }, { path: '/dashboard', component: Dashboard }, { path: '/login', component: Login,name:'Login'} ] }) var vm=new Vue({ router, template: ` <div id="app"> <h1>Navigation Guards</h1> <ul> <li><router-link to="/">/</router-link></li> <li><router-link to="/about">/about</router-link></li> <li><router-link to="/dashboard">/dashboard</router-link></li> </ul> <router-view class="view"></router-view> </div> ` }).$mount('#app')
具体实现的效果

组件内的守卫
beforeRouteEnter beforeRouteEnter beforeRouteLeave
官方模板
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` } }
举个例子1:
其他的组件的写法跟第一个一样的
beforeRouteEnter
// 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` 因为当守卫执行前,组件实例还没被创建,路由也不会改变
所以有写next()时,组件是不会展示的
about.vue
<template>
<div>
<h2>About</h2>
<p>Yay you made it!</p>
<div>{{num}}</div>
</div>
</template>
<script>
export default {
data(){
return {
num: 18
}
},
beforeRouteEnter(to, from, next){
console.log(to.path)
},
beforeRouteLeave (to, from, next){
console.log(to.path);
}
}
</script>
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) import auth from './auth' import About from './components/About.vue' import Dashboard from './components/Dashboard.vue' import Login from './components/Login.vue' function requireAuth (route, redirect, next) { if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: route.fullPath } }) } else { next() } } const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ {path: '/about', component: About}, { path: '/dashboard', component: Dashboard }, { path: '/login', component: Login,name:'Login'} ] }) var vm=new Vue({ router, template: ` <div id="app"> <h1>Navigation Guards</h1> <ul> <li><router-link to="/">/</router-link></li> <li><router-link to="/about">/about</router-link></li> <li><router-link to="/dashboard">/dashboard</router-link></li> </ul> <router-view class="view"></router-view> </div> ` }).$mount('#app')
实际实现效果:
举个例子2:
其他的组件的写法跟第一个一样的
components/About.vue
<template>
<div>
<h2>About</h2>
<p>Yay you made it!</p>
<div>{{num}}</div>
</div>
</template>
<script>
export default {
data(){
return {
num: 18
}
},
beforeRouteEnter(to, from, next){
console.log(to.path)
next(vm=>{
vm.num=19;
})
},
beforeRouteLeave (to, from, next){
console.log(to.path)
}
}
</script>
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) import auth from './auth' import About from './components/About.vue' import Dashboard from './components/Dashboard.vue' import Login from './components/Login.vue' function requireAuth (route, redirect, next) { if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: route.fullPath } }) } else { next() } } const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ {path: '/about', component: About}, { path: '/dashboard', component: Dashboard }, { path: '/login', component: Login,name:'Login'} ] }) var vm=new Vue({ router, template: ` <div id="app"> <h1>Navigation Guards</h1> <ul> <li><router-link to="/">/</router-link></li> <li><router-link to="/about">/about</router-link></li> <li><router-link to="/dashboard">/dashboard</router-link></li> </ul> <router-view class="view"></router-view> </div> ` }).$mount('#app')
实现效果:dashboard地址时,导航栏平没有发生变化,并不会离开
这里注意当我点击

如果想要离开的话,about.vue 这样改:只要在beforeRouteLeave在加入next()
<template>
<div>
<h2>About</h2>
<p>Yay you made it!</p>
<div>{{num}}</div>
</div>
</template>
<script>
export default {
data(){
return {
num: 18
}
},
beforeRouteEnter(to, from, next){
console.log(to.path)
next(vm=>{
vm.num=19;
})
},
beforeRouteLeave (to, from, next){
console.log(to.path);
next();
}
}
</script>
