vue-router导航守卫

导航守卫

官方解释:

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() 注册过的回调。

 

案例:
components/About.vue
<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>

 

 

 

posted @ 2017-11-13 20:50  莺哥  阅读(542)  评论(0编辑  收藏  举报