23

导航钩子

导航钩子类似于生命周期钩子,包含路由进入前,进入后,更新时,退出前等几个周期,主要用于控制导航的前进后退或跳转等。

在开始之前,我们先来写两个路由
新建html,引入vue.js及vue-router.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路由</title>
    <script src="js/vue.js"></script>
    <script src="js/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <div>
            <button><router-link to='/route1'>路由一</router-link></button>
            <button><router-link to='/route2'>路由二</router-link></button>
        </div>
        <router-view></router-view>
    </div>

    <script src="js/router.js"></script>
</body>
</html>

在router.js中定义路由及vue实例

//构建组件
var route1 = Vue.extend({
    template: '<div>路由一内容</div>'
});

var route2 = Vue.extend({
    template: '<div>路由二内容</div>'
});

//定义路由
var router = new VueRouter({
    routes: [
        {
            path: '/route1',
            name: 'route1',
            component: route1
        },
        {
            path: '/route2',
            name: 'route2',
            component: route2
        }
    ]
});

//定义vue实例
var app = new Vue({
    el: '#app',
    router
})

打开浏览器,查看效果

1.全局钩子

定义路由之后,接着就可以使用router.beforeEach定义全局钩子
在router.js中定义路由后面加上如下代码

router.beforeEach((to,from,next) => {
    console.log(to)
    console.log(from)
})

全局钩子作用于所有路由,里面的参数to表示即将要进入的路由对象,from表示即将要离开的路由对象,next是继续跳转或中断的方法。
我们来看一下打印出的对象

我们的操作是点击路由一按钮,即将由'/'跳转至'/route1',可以看到打印出的第一个对象to的path为'/route1',第二个对象from的path为'/'。
有一个问题,点击按钮之后路由并没有进行跳转,这是因为我们没有写next方法。next方法有以下3种:

1.next() 默认跳转
2.next(false)保持当前路由不进行跳转

3.next('路由路径') 指定路由跳转

(1)默认跳转
我们先来试第一种

router.beforeEach((to,from,next) => {
    console.log(to)
    console.log(from)
    next()
})

打开浏览器,可以看到路由跳转正常,并且以默认的路由进行跳转

(2)保持当前路由不进行跳转
如果不写next方法就不会进行跳转,那么与next(false)的区别就在于,后者是不管url怎么改变,也会重置到from对应的路由。

router.beforeEach((to,from,next) => {
    console.log(to)
    console.log(from)
    next(false)
})

可以看到点击按钮并无反应,在地址栏输入其他路由也跳转回当前路由

(3)指定路由跳转
这个方法最好不要写在全局钩子中,不然会陷入无限循环,跳转到指定路由又触发该导航钩子又进行跳转

2.路由内钩子

导航钩子也可以通过beforeEnter写在某个路由内部

var router = new VueRouter({
    routes: [
        {
            path: '/route1',
            name: 'route1',
            component: route1,
            meta:{title: '路由一'}
            beforeEnter: function(to,from,next){
                console.log(to)
                console.log(from)
                next()
            }
        },
        {
            path: '/route2',
            name: 'route2',
            component: route2,
            meta:{title: '路由二'}
        }
    ]
});

这样只在路由'/route1'下才会触发该钩子

3.组件内钩子

组件内钩子有三种

var route1 = Vue.extend({
    template: '<div>路由一内容</div>',
    //对应该组件的路由被确认之前,此时还未创建组件实例
    beforeRouteEnter:function(to,from,next){
        
    },
    //对应该组件的路由被重复调用之时,如嵌套路由,此时组件实例已被创建
    beforeRouteUpdate:function(to,from,next){

    },
    //即将离开对应该组件的路由时
    beforeRouteLeave:function(to,from,next){

    }
});

路由元信息

定义路由的时候可以设置meta字段

var router = new VueRouter({
    routes: [
        {
            path: '/route1',
            name: 'route1',
            component: route1,
            meta:{title: '路由一'},
        },
        {
            path: '/route2',
            name: 'route2',
            component: route2,
            meta:{title: '路由二'}
        }
    ]
});

通过这个我们可以在全局钩子中设置页面的标题之类的,例如

router.beforeEach(function(to,from,next){
    console.log(to)
    console.log(from)
    if(to.meta.title){
        document.title = to.meta.title
    }else{
        document.title = '路由'
    }
    
    next()
})

查看效果

过渡动效

在路由中可以给路由视图<router-view><transition>标签设置总的过渡类名

<transition name="fade" v-on:before-enter="enter">
    <router-view></router-view>
</transition>

其中before-enter为钩子函数,钩子函数有以下几种,本例中只写了第一种“进入之前”

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>

接着给fade类写过渡样式

.fade-enter-active, .fade-leave-active{transition: all 0.5s ease;}
.fade-enter, .fade-leave-active{opacity:0;}

查看效果


Reachel
2.6k 声望219 粉丝