爱客仕-前端团队博客园

vue-router的简单流程

前言

因为路由权限问题,简单的看了一下vue-router(v0.7.13)。整理了一下router的一个简单过程

beforeEach -> canReuse -> canDeactivate -> canActivate -> deactivate -> afterEach -> activate

其中canDeactivate | canActivate | deactivate | activate这几个钩子涉及组件复用的问题,所以有可能不会被调用,但是当canReuse返回false时,就一定会被调用了

注:canDeactivate,deactivate与canActivate,activate分别作用于要销毁要生成的组件。
如:a/b -> a/c,这里b组件要被销毁,c组件要被生成。

一、vue-router组成

vue-router组件有三个部分:

  1. link:即v-link
  2. view:元素指令,即
  3. router:核心部分

二、vue-router简单的一个流程

  1. url 变化

  2. history监听(onChange事件)
    例如:

    1
    2
    3
    4
    // hashbang路由模式,如:http://localhost/#!/login
    window.addEventListener('hashchange', () => {})
    // h5 history路由模式,如:http://localhost/login
    window.addEventListener('popstate', () => {})
  3. 调用路由匹配( this._match)
    会保存老的transition和新的transition

  4. 走一遍beforeEach

  5. 走startTransition开始进入transition的撕逼周期(也算是vue-router的核心所在)
    这里会涉及组件复用的问题
    1). canReuse:调用canReuse钩子

    看当前的<vue-router>和将要跳转的<vue-router>之间有没有可重用的组件
    a/b/c
    a/b/d  =>  可复用[a,b],需要销毁[c],需要生成[d]
    

    2). canDeactivate(c):调用canDeactivate钩子

    1
    2
    3
    route: {
    canDeactivate() {}
    }

    3). canActivate(d):调用canActivate钩子

    4). deactivate(c):调用deactivate钩子

    5). _afterEachHooks(c):调用afterEach钩子

    6). reuse([a,b]):调用data钩子

    7). activate(d) :调用activate | data钩子

  6. 若activate(d),则调用vue中的build方法,新生成component

三、两个应用场景

1.组件复用(a/b/:id)

这次遇到了类似(a/b/:id)这样的路由,这种路由一直都只是(:id)在变化,一直是被复用的。所以不会走canDeactive, canActivate,deactivate,activate,只会调用router.beforeEachcanReuserouter.afterEachthis.data当然没有被transition.abort()的前提下。

1
2
3
4
5
6
7
new VueRouter().beforeEach(function (transition) {
if (transition.to.path === '/forbidden') {
transition.abort()
} else {
transition.next()
}
})
1
2
3
new VueRouter().afterEach(function (transition) {
console.log('成功浏览到: ' + transition.to.path)
})
1
2
3
4
5
6
7
8
route: {
canReuse() {
return true
},
data() {
// TODO 没有被transition.abort()的时候,会被调用
}
}

2.路由切换

有一种场景是组件a切换到组件b时,想要先停留在a,等b获取了数据才进行切换,想做到这个可以使用waitForData,在b组件作如下操作:

1
2
3
4
5
6
route: {
data() {
// TODO 数据请求加载
},
waitForData: true //数据加载完在切换
}