Vue-router之导航守卫

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/grapelove01/article/details/82620031

导航守卫

全局导航守卫

全局钩子

// client/index.js
router.beforeEach((to, from, next) => { // 跳转前
  console.log('before each invoked')
  next() // next 必须执行,才能跳转
})

router.beforeResolve((to, from, next) => {
  console.log('before resolve invoked')
  next()
})

router.afterEach((to, from) => { // 跳转后,不需要 next
  console.log('after each invoked')
})

beforeEach

进行数据校验,比如验证页面,用户需要登录后才能显示,设置跳转到 login 页面

// client/index.js
router.beforeResolve((to, from, next) => {
  console.log('before resolve invoked')
  if (to.fullPath === '/app') {
    next('/login')  // 或者 next({path: '/login})
  } else {
    next()
  }
})

路由配置中增加钩子

beforeEnter 调用顺序是在 beforeEach 和 beforeResolve 之间。

// client/config/routes.js
export default [
  {
    path: '/app',
    component: Todo,
    beforeEnter (to, from, next) {
      console.log(' app route before enter')
      next()
    }
  }
]

组件内部增加钩子

// todo.vue
export default {
  beforeRouteEnter (to, from, next) {
    console.log('todo before enter')
    next()
  },
  beforeRouteUpdate (to, from, next) {
    console.log('todo update enter')
    next()
  },
  beforeRouteLeave (to, from, next) {
    console.log('todo leave enter')
    next()
  },

点击跳转 login 时

控制台

todo leave enter  组件被离开
before each invoked 新路由进入之前
before resolve invoked
after each invoked

点击跳转 app 时

before each invoked
app route before enter 路由配置的 beforeEnter
todo before enter 组件内的 beforeEnter
before resolve invoked 而beforeResolve 要等全局的 beforeEach、路由配置的 beforeEnter、组件内都触发才出发
after each invoked

同一个组件在不同路由下面显示的情况下 beforeRouteUpdate 才会触发

例如路由传参的情况下,切换路由,组件会进行复用。如果不这样做,需要通过 watch 监听 id。

// routes.js
{
    path: '/app/:id',
    component: Todo
  },
// app.vue
<template>
  <div id="app">
    <div id="cover"></div>
    <router-link to="/app/123">app123</router-link>
    <router-link to="/app/456">app456</router-link>
    <router-link to="/login">login</router-link>
  </div>
</template>
// todo.vue
  beforeRouteEnter (to, from, next) {
    console.log('todo before enter', this)
    next(vm => {
      console.log('after enter vm.id is ', vm.id)
    })
  },
  beforeRouteUpdate (to, from, next) {
    console.log('todo update enter')
    next()
  },
  beforeRouteLeave (to, from, next) {
    console.log('todo leave enter')
    if (global.confirm('are you sure?')) {
      next()
    } else {
    }
  },

路由钩子在组件内部的应用

beforeRouteEnter 和 beforeRouteUpdate 获取数据,当我们进入页面,数据已经渲染好了

beforeRouteEnter (to, from, next) {
    console.log('todo before enter', this)
    next(vm => { 
      console.log('todo enter vm.id is ', vm.id)
    })
  },

beforeRouteLeave 弹出确认框,是否离开

beforeRouteLeave (to, from, next) {
    console.log('todo leave enter')
    if (global.confirm('are you sure?')) {
      next()
    } else {
    }
  },

关于 beforeRouteUpdate

路由参数不同,组件相同时,生命周期是不会触发,导致数据不更新,应该使用 beforeRouteUpdate 或者 watch

命名视图

不同的 router-view 显示不同的组件

// client/app.vue
<template>
  <div id="app">
    <transition name="fade">
      <router-view />
    </transition>
      <router-view name="a"/>
  </div>
</template>
// client/config/routes.js
export default [
  {
    path: '/app',
    components: {
      default: Todo,
      a: Login
    }
  },
  {
    path: '/login',
    components: {
      default: Login,
      a: Todo
    }
  }
]

常见的三栏布局,菜单切换,可以用这种方式,当然传统的 layout 也可以实现。

异步路由(异步加载组件)

当路由非常多时,通过 webpack 一次性打包所有代码,导致 js 文件非常大,初始加载时间非常长。

异步路由:对于不同的路由,只加载对应代码和项目核心代码;而对应页面的代码,访问时再加载。

使用

使用异步路由,只需在对应组件使用 import 引入对应组件即可,这样当我们访问路由时,才会加载。

// import Todo from '../views/todo/todo.vue'
// import Login from '../views/login/login.vue'

export default [
  {
    path: '/app/:id',
    props: 'true',
    component: () => import('../views/todo/todo.vue')
    }
  },
  {
    path: '/login',
    component: () => import('../views/login/login.vue')
  }
]

安装 babel 插件

程序不支持直接在 component 部分写 import,需要安装 babel 插件。

npm i babel-plugin-syntax-dynamic-import -D

// .babelrc
{
  "presets": [
    "env"
  ],
  "plugins": [
    "transform-vue-jsx",
    "syntax-dynamic-import"  // 添加配置
  ]
}

注意

核心代码中不要使用异步加载的组件,这样我们切换路由会没有效果。

猜你喜欢

转载自blog.csdn.net/grapelove01/article/details/82620031