theme: condensed-night-purple
highlight: a11y-dark
这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天
为什么使用导航守卫?
我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢? 网页标题是通过
来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变.
但是我们可以通过JavaScript来修改<title>的内容.window.document.title = '新的标题'.
<p>那么在Vue项目中, 在哪里修改? 什么时候修改比较合适呢?
普通的修改方式:
我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中.
通过mounted声明周期函数, 执行对应的代码进行修改即可.</p>
<p><strong>生命周期函数</strong>
组件被创建出来 后回调created函数
模板挂载到DOM上 后回调mounted函数
界面发生一次刷新 就调用一次updated函数 </p>
<p>但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).
<code>js
export default {
name : "Home",
// created () {
// console.log("crested");
// document.title = "首页"
// }
};
</code></p>
<p>有没有更好的办法呢? 使用导航守卫即可.</p>
<p>监听网页跳转过程</p>
<h1>什么是导航守卫?</h1>
<p>vue-router提供的导航守卫主要用来监听<strong>监听路由的进入和离开的</strong>.</p>
<p>vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.</p>
<h1>导航守卫使用</h1>
<p>我们可以利用beforeEach来完成标题的修改.
首先, 我们可以在钩子当中定义一些标题, 可以利用meta来定义 (meta:元数据--描述数据的数据)
其次, 利用导航守卫,修改我们的标题.
</p>
<p>导航钩子的三个参数解析:
to: 即将要进入的目标的路由对象.
from: 当前导航即将要离开的路由对象.
next: 调用该方法后, 才能进入下一个钩子. 必须写</p>
<p>next: Function :一定要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参数。</p>
<ul>
<li>next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed (确认的)。</li>
<li>next(false): 中断当前的导航。如果浏览器的URL改变了(可能是用户手动或者浏览器后退按钮),那么URL地址会重置到from路由对应的地址。</li>
<li>next("/")或者next({ path: '/'}): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next传递任意位置对象,且允许设置诸如replace: true,name :'home'之类的选项以及任何用在router-link的 to prop或router.push中的选项。
</li>
<li>next(error): (2.4.0+)如果传入next的参数是一个Error实例,则导航会被终止且该错误会被传递给router.onError()注册过的回调。
<strong>确保要调next方法,否则钩子就不会被resolved。</strong></li>
</ul>
<p>```js
{
path : '/profile',
component : Profile,
meta : {
title : '档案'
}
}</p>
<p>// 前置守卫guard 表示回调
router.beforeEach((to, from, next) =>{
// 从from跳转到to
// matched:用于嵌套路由,第一个元素为最外层的大标题
document.title = to.matched[0].meta.title
console.log("++++");
next()
})</p>
<p>// 后置钩子hook
router.afterEach((to, from) => {
console.log("----");
})</p>
<p>```</p>
<h1>导航守卫补充</h1>
<p>补充一: 如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.</p>
<p>补充二: 上面我们使用的导航守卫, 被称之为<strong>全局守卫</strong>(只要进行路由跳转,就会执行
<strong>路由独享的守卫</strong>.(只有进入某个路由才会回调,可以在路由配置上直接定义beforeEnter守卫
<strong>组件内的守卫</strong>.</p>
<p>更多内容, 可以查看官网进行学习:
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E8%B7%AF%E7%94%B1%E7%8B%AC%E4%BA%AB%E7%9A%84%E5%AE%88%E5%8D%AB</p>
<p>```js
// 你可以在路由配置上直接定义beforeEnter守卫:
// 这些守卫与全局前置守卫的方法参数是一样的。
const router = new VueRouter({
routes:[
{
path: "/foo" ,
component: Foo,
beforeEnter: (to,from,next)=>{
...
}
}]
})</p>
<p>```</p>
<p>```js
// 最后,你可以在路由组件内直接定义以下路由导航守卫:
// beforeRouteEnter
// beforeRouteUpdate (2.2新增)
// beforeRouteLeave</p>
<p>const Foo = {
template: <code>...</code>,
beforeRouteEnter (to,from,next){
//在渲染该组件的对应路由被confirm前调用
//不!能!获取组件实例'this'
//因为当守卫执行前,组件实例还没被创建
}
beforeRouteUpdate (to,from,next){
//在当前路由改变,但是该组件被复用时调用
//举例来说,对于一个带有动态参数的路径/foo/:id,在/foo/1和 /foo/2之间跳转的时候
//由于会渲染同样的 Foo组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
//可以访问组件实例'this'
},
beforeRouteLeave (to,from,next){
// 导航离开该组件的对应路由时调用
// 可以访问组件实例'this'
}
}</p>
<p>```</p>