前端vue入门(纯代码)35_导航守卫

news2024/11/24 18:57:06

星光不问赶路人,时光不负有心人

33.Vue Router--导航守卫

导航守卫

正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

全局前置守卫

你可以使用 router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })

//全局前置守卫
router.beforeEach((to,from,next) =>{
  //第一个参数to,包含的内容是切换后的路由对象,也就是跳转后的路由对象
  //第二个参数from,包含的内容的是切换前的路由对象,也就是跳转前的路由对象
  //第三个参数next(),是否往下执行,执行的话,如果不写的话路由就不会跳转,操作将会终止
    console.log('前置路由守卫',to,from,next)  
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve【解析】 完之前一直处于 等待中

① 执行时间
初始化时执行,每次路由切换前执行
② 使用场景
全局前置守卫通常用来进行路由跳转的一些信息判断,判断是否登录,是否拿到对应的路由权限等等。

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。【进行下一个路由】
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: truename: 'home' 之类的选项以及任何用在 router-linkto prop或 router.push 中的选项。
    • next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。这里有一个在用户未能验证身份时重定向到 /login 的示例:

// BAD  错误示范
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  // 如果用户未能验证身份,则 `next` 会被调用两次
  next()
})
// GOOD  推荐写法
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})

route/index.js

// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router';
//引入组件
import About from '../pages/About';
import Home from '../pages/Home';
import Cartoon from '../pages/Cartoon';
import Stars from '../pages/Stars';
import Detail from '../pages/Detail';

//创建并暴露一个路由器
const router = new VueRouter({
  // 定义一些路由
  // 每个路由都需要映射到一个组件。
  routes: [
	//配置路由路径和路由组件
	{
	  name: 'firstabout',
	  path: '/about',
	  component: About, //要跳转到的组件
      meta:{title:'关于'}
	},
	{
	  //一级路由配置
      name: 'firsthome',
	  path: '/home',
	  component: Home,
      meta:{title:'主页'},
	  children: [
		{
		  //二级路由配置
		  name: 'Hcartoon',
		  path: 'cartoon',
		  component: Cartoon,
          meta:{isAuth: true,title:'卡通'},
		},
		{
		  //二级路由配置
          name:'secondstars',
		  path: 'stars',
		  component: Stars,
          meta:{isAuth: true,title:'明星'},
		  children: [
			{
              //三级路由配置
              name: 'xiangqing',
              /*使用占位符声明,接收params参数,相当于说先占个位置,在路由组件中就可以按照位置进行参数传递*/
              // params方法传参配置
              // path: 'detail/:title/:works',
              // query方法传参配置
              path: 'detail',
              component: Detail,
              meta:{isAuth: true,title:'详情'},
			  //props的第三种写法,props值为函数,该函数返回的对象中每一组key-value都会通过props传给路由组件
			  // query方法传参配置
			  props($route) {
				return {
                    // works: $route.params.works,
                    title: $route.query.title,
                    works: $route.query.works,
                    a: 1,
                    b: 'hello',
                };
			  },
                // params方法传参配置
                /* props($route) {
                    return {
                       works: $route.params.works,
                       title: $route.params.title,
                       a:1,
                       b:'hello'
                    };
                }, */
			},
		  ],
		  },
		],
		},
	],
});

//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
  console.log('前置路由守卫',to,from)
  console.log('next函数',next)
   //判断是否需要鉴权
  if (to.meta.isAuth) {
    if (localStorage.getItem('userName') === 'xujianfei') {
      document.title =  to.meta.title
      next()
    }else{
      alert('用户名不对,无权限查看!')
    }
  }else{
    document.title =  to.meta.title
    next()
  }
})

export default router

全局后置钩子

  • 你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

  • 全局后置守卫,组件初始化时调用,每次路由切换之后调用,路由切换之后指的就是,举个例子说,当前我在A路由组件,我要切换到B路由组件,那么后置路由守卫就是在我点了切换按钮B路由组件呈现到页面中后被调用。

① 执行时间
初始化时执行,每次路由切换后执行
② 使用场景
对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
③ 注意项
不会接受 next函数,也不会改变导航本身
④ 使用方法
可以使用 router.afterEach 注册一个全局后置守卫

const router = new VueRouter({ ... })

//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach( (to,from)=>{
  console.log('后置路由守卫',to,from)
  //修改网页的title
  document.title =  to.meta.title ||'小白学习路由守卫'
})

路由独享的守卫

  • 组件独享守卫是在进入组件时被调用,区别就在于,想对那个路由进行权限控制就直接在其路由配置项中添加守卫,作用域也仅限于该路由

① 执行时间
独享守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。它们只有在 从一个不同的 路由导航时,才会被触发。
② 注意项
独享守卫没有后置,可以全局后置路由守卫搭配使用
③ 使用方法
直接在路由配置上使用 beforeEnter定义独享守卫

你可以在路由配置上直接定义 beforeEnter 守卫:【逻辑判断也在beforeEnter里面写】


const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter(to,from,next){
        //逻辑判断写在此处
    },
  },
]

这些守卫与全局前置守卫的方法参数是一样的。

  • 全局路由守卫服务的是所有路由组件,而独享路由守卫只服务于被配置的单个路由组件

组件内的守卫

当使用路由规则进入该组件或离开该组件时,就会触发组件内守卫的调用,而组件内守卫的作用于范围也仅限于该组件

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • 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`
  }
}

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdatebeforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

beforeRouteLeave (to, from, next) {
  const answer = alert('还未保存,确定要离开吗')//放行
  if (answer) {
    next()//放行
  } else {
    next(false)//取消
  }
}

唯一不同于之前的就是:BeforeRouterLeave(),它并不像全局后置守卫一样在路由组件加载完成之后调用,而是在你切换出这个组件后被调用,也就是离开这个组件后被调用,在开发中,我们也可以使用BeforeRouterLeave() 来完成某些操作,比如当我要切换出该组件事,我希望该组件的操作能暂停,而不是一直运行,只有当我切换回该组件时,又再次运行,这样的操作就可以配合着beforeRouteEnter() 来完成,也可以提高应用的性能。

完整的导航解析流程

  1. 导航被触发。

  2. 在失活的组件里调用 离开守卫beforeRouteLeave

  3. 调用全局前置守卫 beforeEach

  4. 在重用的组件里调用更新守卫 beforeRouteUpdate (2.2+)。

    举例来说,对于一个带有动态参数的路径 /users/:id,在 /users/1/users/2 之间跳转的时候, 由于会渲染同样的 UserDetails 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

  5. 在路由配置里调用 独享守卫beforeEnter

  6. 解析异步路由组件。

  7. 在被激活的组件里调用 进入守卫beforeRouteEnter

  8. 调用全局解析守卫 beforeResolve (2.5+)。

  9. 导航被确认。

  10. 调用全局后置守卫afterEach

  11. 触发 DOM 更新。

  12. 调用 进入守卫beforeRouteEnter 中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

路由元信息

通过路由记录的 meta 属性可以定义路由的元信息。使用路由元信息可以在路由中附加自定义的数据,例如:

  1. 每个路由给予独立的标题;
  2. 管理后台的路由,部分页面需要限制一些访问权限;
  3. 通过路由来自动生成侧边栏、面包屑;
  4. 部分路由的生命周期需要做缓存( Keep Alive );
  5. 其他更多业务场景…

我们可以在导航守卫或者是路由对象中访问路由的元信息数据。

const routes = [
  {
    path: '/posts',
    component: PostsLayout,
    children: [
      {
        path: 'new',
        component: PostsNew,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true, title:'创建帖子'}
      },
      {
        path: ':id',
        component: PostsDetail,
        // 任何人都可以阅读文章
        meta: { requiresAuth: false ,title:'阅读文章'}
      }
    ]
  }
]

后续等vue2所有基础知识学完后,整个学习笔记的代码会上传到github

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp JS文件里面调用自定义组件(不用每个页面在template中加组件标签)

前言 工具:uniapp 开发端:微信小程序 其他:uview 2.0 场景:路由器里面,统一验证是否已登录,如果没登录,则直接弹出登录弹窗出来,不管哪个页面都如此。 效果如下: 直接上…

【笔试强训选择题】Day29.习题(错题)解析

作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:笔试强训选择题 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!&#xff…

rsync—远程同步

目录 一:rsync概述 1.1rsync简介 1.2rsync同步方式 二:rsync特性 三:rsync同步源 四:rsync与cp、scp对比 五:常用rsync命令 六:rsync本地复制实例 七:配置源的俩种表示方法 八&#x…

[NLP]Huggingface模型/数据文件下载方法

问题描述 作为一名自然语言处理算法人员,hugging face开源的transformers包在日常的使用十分频繁。在使用过程中,每次使用新模型的时候都需要进行下载。如果训练用的服务器有网,那么可以通过调用from_pretrained方法直接下载模型。但是就本人…

安全DNS,状态码,编码笔记整理

一 DNS DNS(Domain Name System)是互联网中用于将域名转换为IP地址的系统。 DNS的主要功能包括以下几个方面: 域名解析:DNS最主要的功能是将用户输入的域名解析为对应的IP地址。当用户在浏览器中输入一个域名时,操作…

工程安全监测无线振弦采集仪在建筑物中的应用

工程安全监测无线振弦采集仪在建筑物中的应用 工程安全监测无线振弦采集仪是一种用于建筑物结构安全监测的设备,它采用了无线传输技术,具有实时性强、数据精度高等优点,被广泛应用于建筑物结构的实时监测和预警。下面将从设备的特点、应用场…

力扣热门100题之接雨水【困难】

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3…

如何使用GPT作为SQL查询引擎的自然语言

​生成的AI输出并不总是可靠的,但是下面我会讲述如何改进你的代码和查询的方法,以及防止发送敏感数据的方法。与大多数生成式AI一样,OpenAI的API的结果仍然不完美,这意味着我们不能完全信任它们。幸运的是,现在我们可以…

Packet Tracer – 配置动态 NAT

Packet Tracer – 配置动态 NAT 拓扑图 目标 第 1 部分:配置动态 NAT 第 2 部分:验证 NAT 实施 第 1 部分: 配置动态 NAT 步骤 1: 配置允许的流量。 在 R2 上,为 ACL 1 配置一个语句以允许属于 172.16.0.…

【JVM】浅看JVM的运行流程和垃圾回收

1.JVM是什么 JVM( Java Virtual Machine)就是Java虚拟机。 Java的程序都运行在JVM中。 2.JVM的运行流程 JVM的执行流程: 程序在执行之前先要把java代码转换成字节码(class文件),JVM 首先需要把字节码通过…

Visio/PPT/Matlab输出300dpi以上图片【满足标准投稿要求】

1. visio 遵照如下输出选项,另存为tif格式文件时,选择正确输出便是300dpi以上 2. matlab 文件选项选中导出设置,在渲染中选择dpi为600,导出图片即可,科研建议选择tif格式文件 3.ppt 打开注册表,winr键…

【报错】在python3.9环境下安装sqlmap报错

问题描述 报错内容: missing one or more core extensions (‘ssl’, ‘sqlite3’) most likely because current version of Python has been built without appropriate dev packages 原因分析: 缺少一个或多个核心扩展(‘ssl’、‘sqlit…

常见的栈溢出StackOverFlow 与 内存溢出OutOfMemory的区别

0、前言:内存模型 对于多线程运行情况下的jvm内存,我们应当知道: 每创建一个线程,jvm就会为其分配一块线程私有的工作内存,其中包括程序计数器、栈,等等。 对于每一个线程私有的栈,当线…

怎么限制文件打开次数、打开时间?

一些公司出于业务需求,可能会给客户或者合作伙伴发一些涉密图纸、文档、文件等重要文件,但是又不想文件被外发泄露随意传播,今天就教大家一个方法限制文件外发后别人打开这个文件的打开次数、打开时间、另存为等操作。 设置方法 本篇文章测试…

page _refcount和_mapcount字段

linux page有两个非常重要的引用计数字段_refcount和_mapcount,都是atomic_t类型,其中,_refcount表示内核中应用该page的次数。当_refcount 0时,表示该page为空闲或者将要被释放。当_refcount > 0,表示该page页面已…

APP-脱壳+反编译

APP反编译加固-自动查壳脱壳 为什么要脱壳? 因为不脱壳无法进行反编译 查壳工具:https://pan.baidu.com/s/1rDfsEvqQwhUmep1UBLUwSQ 密码: wefd 脱壳工具:https://github.com/CodingGay/BlackDex 查壳演示: 使用Java运行jar包&a…

浙江大学软件学院2022保研经历分享

首先,我想强调一点,如果我们只是一个普通的非211,985的本科生,一定要参加浙江大学每年7月份组织的夏令营,因为浙大的夏令营是一个海王营,基本上不会对入营的学生做筛选,但是要想获得优秀营员&am…

pandas笔记:groupby整理

0 数据集 # Visual Python: Data Analysis > File vp_df pd.read_csv(https://raw.githubusercontent.com/visualpython/visualpython/main/visualpython/data/sample_csv/fish.csv) vp_df 1 单列聚合 vp_df.groupby(Type)[Kg].mean()Type mackerel 1.417456 salmon…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能:2.2 目录界面:2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…