Vue--Router--钩子函数(导航守卫)--使用场景/实例

原文网址:

简介

说明

        本文介绍Vue Router(路由)的钩子函数(导航卫士)的使用场景。

        Vue Router的导航守卫用法,官网中介绍的很详细了,本处只介绍使用场景。

官网

导航守卫 | Vue Router

钩子函数种类

全局钩子函数

beforeEach():每次路由进入之前执行的函数。
afterEach():每次路由进入之后执行的函数。
beforeResolve():2.5新增

单个路由的钩子函数

beforeEnter()

组件内的路由钩子函数

beforeRouteEnter()
beforeRouteLeave()
beforeRouteUpdate()

导航执行流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

使用场景

全局的钩子

beforeEach

全局前置导航守卫,加载页面之前执行。

应用场景

  1. 页面跳转前处理。例如:拦截需要登录的页面,跳转到登录页面
  2. 进入页面登录判断、管理员权限判断、浏览器判断

示例代码

// 写在路由的js文件中
router.beforeEach((to, from, next) => {
    const role = localStorage.getItem('ms_username');
    if(!role && to.path !== '/login'){
        next('/login');
    }else if(to.meta.permission){
        // 如果是管理员权限则可进入,这里只是简单的模拟管理员权限
        role === 'admin' ? next() : next('/403');
    }else{
        // 简单的判断IE10及以下不进入富文本编辑器,该组件不兼容
        if(navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor'){
            Vue.prototype.$alert(
            	'vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏览器查看', 
            	'浏览器不兼容通知', 
            	{confirmButtonText: '确定'}
            );
        }else{
            next();
        }
    }
})

单个路由的钩子

beforeEnter

进入某个个路由前执行。

应用场景

  1. 将上一个组件传过来的参数拼到新的路由的后边

示例代码

// 写在路由文件的js的某个路由中
const routes = [
  {
    path: '/',
    beforeEnter: (to, from, next) => {
      const href = window.location.href
      const queryString = href.slice(href.indexOf('?'))
      // 即将跳转到某个路由之前,把上一个路由的参数拼接在要重定向的路由的后面
      // 可以用来初始化页面数据
      next({ path: `/home/dashboard${queryString}`, replace: true })
    }
  },
  
 // ...
  
]

组件内的钩子

应用场景1:清除当前组件中的定时器

        当一个组件中有一个定时器时, 在路由进行切换的时候, 可使用beforeRouteLeave将定时器进行清楚, 以免占用内存。

beforeRouteLeave (to, from, next) {  
 	window.clearInterval(this.timer) //清除定时器   
 	next()
}

应用场景2:页面中有未关闭的窗口, 或未保存的内容时, 阻止页面跳转 

        如果页面内有重要的信息需要用户保存后才能进行跳转, 或者有弹出框的情况,应该阻止用户跳转,结合vuex状态管理(dialogVisibility是否有保存)

beforeRouteLeave (to, from, next) {
	 //判断是否弹出框的状态和保存信息与否
	 if (this.dialogVisibility === true) {
	    this.dialogVisibility = false //关闭弹出框
	    next(false)                   //回到当前页面, 阻止页面跳转
	  }else if(this.saveMessage === false) {
	    alert('请保存信息后退出!') //弹出警告
	    next(false)              //回到当前页面, 阻止页面跳转
	  }else {
	    next() //否则允许跳转
	  }
 }

应用场景3:保存相关内容到Vuex中或Session中

当用户需要关闭页面时, 可以将公用的信息保存到session或Vuex中

 beforeRouteLeave (to, from, next) {
    localStorage.setItem(name, content); //保存到localStorage中
    next()
}

写法

需求:通过判断登录状态的 meta 属性auth来确定是否需要登录

写法1:在Router定义处使用

router/index.js

import Vue from 'vue'
import Router from 'vue-router'

const vueRouter = new Router({
    routes: [
    	{
		 path: '/login',
          name: 'login',
          component: login,
		},
        {
          path: '/index',
          name: 'index',
          component: index,
          meta:{auth:true,keepAlive: false},
          children: [
            {name: 'children1', path: 'children1', component: children1},
            {name: 'children2', path: 'children2', component: children2}
          ]
        }
    ]
});

vueRouter.beforeEach(function (to, from, next) {
    const nextRoute = [ 'index', 'children1', 'children2'];
        // const auth = store.state.auth; //在vueX中保存状态
        const auth = meta.auth;
    //跳转至上述3个页面
    if (nextRoute.indexOf(to.name) >= 0) {
        //未登录
        if (!auth.IsLogin) {
            vueRouter.push({name: 'login'})
        }
    }
    //已登录的情况再去登录页,跳转至首页
    if (to.name === 'login') {
        if (auth.IsLogin) {
            vueRouter.push({name: 'index'});
        }
    }
    next();
});

写法2:在main.js中插入

router/index.js

import Vue from 'vue'
import Router from 'vue-router'

const vueRouter = new Router({
    routes: [
    	{
		 path: '/login',
          name: 'login',
          component: login,
		},
        {
          path: '/index',
          name: 'index',
          component: index,
          meta:{auth:true,keepAlive: false},
          children: [
            {name: 'children1', path: 'children1', component: children1},
            {name: 'children2', path: 'children2', component: children2}
          ]
        }
    ]
});
export default vueRouter;

main.js

import vueRouter from './router'
vueRouter.beforeEach(function (to, from, next) {
    const nextRoute = [ 'index', 'children1', 'children2'];
        // const auth = store.state.auth; //在vueX中保存状态
        const auth = meta.auth;
    //跳转至上述3个页面
    if (nextRoute.indexOf(to.name) >= 0) {
        //未登录
        if (!auth.IsLogin) {
            vueRouter.push({name: 'login'})
        }
    }
    //已登录的情况再去登录页,跳转至首页
    if (to.name === 'login') {
        if (auth.IsLogin) {
            vueRouter.push({name: 'index'});
        }
    }
    next();
});

 

上一篇:nvm node version manage(node版本管理)


下一篇:在 Android 中使用生物识别,kotlin开发思维