过了一遍vue2的router,整理一下小结

目录

一、前端路由的概念与原理

1.1 什么是路由

1.2 路由的工作方式

二、vue-router的基本使用

2.1 安装、配置、使用router

2.2 redirect重定向

三、嵌套路由

3.1 声明子路由的规则

3.2 默认子路由

四、动态路由

4.1 动态路由的概念

4.2 动态路由取参方式一(:参数项)

4.3 动态路由取参方式二(props传参)– 常用

4.3 动态路由 – query & fullPath

query传参取值

五、编程式导航跳转

5.1 声明式导航 & 编程式导航

5.2 vue-router中的编程式导航API

六、导航守卫

6.1 什么是导航守卫

6.2 全局 前置 守卫

6.3 守卫方法的3个形参

6.4 next() 的三个调用方式

6.5 控制访问权限


一、前端路由的概念与原理

1.1 什么是路由

路由(router)就是 对应关系

地址与页面上组件的对应关系

不同的地址展示不同的组件

路由就是:Hash地址 与 组件 之间的 对应关系

1.2 路由的工作方式

1、用户 点击了 页面上的 路由链接 (本质上是a链接)

2、导致了 URL地址栏 中的 Hash值 发生了变化

3、前端路由监听到了Hash地址的变化

4、前端路由把当前 Hash地址对应的组件 渲染到浏览器中

二、vue-router的基本使用

2.1 安装、配置、使用router

1、安装vue-router包

npm i vue-router@3.5.2 -S

此时,package.json里多出路由安装,后面是版本号

 "vue-router": "^3.5.2"

2、创建路由模块

在src源代码目录下,创建 router/index.js 路由模块,并进行配置

// src/router/index.js文件就是当前项目的路由模块// 路由模块的配置有四部//1、导入Vue 和 VueRouter 的包import Vue from 'vue'import VueRouterfrom 'vue-router'//2、调用 Vue.use()函数,把VueRouter安装为Vue项目的插件//在Vue里面装插件,调用 use()函数Vue.use(VueRouter) //3、创建路由的实例对象const router = new VueRouter()//4、向外共享路由的实例对象export default router

这个时候,去main.js文件上,把router挂载到Vue实例上(router被共享了)

//导入 routerimport router from './router' /*注意:在模块化导入的时候,如果给定的不是具体的文件(是文件夹)则默认导入这个文件夹下,名字叫 index.js 的文件而且,router目录是拿来配置路由的,所以里面只需要创建一个index.js文件所以可以不用写全为:import router from './router/index.js'*///在Vue实例上挂载路由new Vue({render: h => h(App),router}).$mount('#app')---------------------/*因为路由导入的时候,取的名字是router,和实例里面的router属性名同名,所以可以简写为一个router如果是这么导入的话import href from './router'在实例上就需要这么挂载new Vue({render: h => h(App),router:href}).$mount('#app')*/

当配置结束以后

3、导入并挂载路由模块

在router/index.js(路由模块)中声明组件路由

//1、导入需要声明成路由的组件//导入路由需要的组件import Home from '@/components/Home.vue'import Movie from '@/components/Movie.vue'import About from '@/components/About.vue'//2、在Vue实例内绑定路由和hash的对应关系const router = new VueRouter({//在路由的实例对象中//用一个 routes:[]数组,来定义 hash地址与组件之间的对应关系routes:[{path:'/', //path指的是路由的hash地址,跳转的时候用这个路径跳转到对应组件,如果path只给了一个 /,则是首页默认展示component:Home //要展示的组件},{path:'/movie',component:Movie},{path:'/About',component:About}]})

这个时候,组件的路由就配置完成了!

在App组件里面,用router-view去展示组件即可

4、声明 路由链接 占位符

只要在项目中安排和配置了 vue-router

就可以使用 router-view 组件

占位符:

作用:给路由组件进行占位,组件的路由进行切换的时候,组件会在这个地方进行展示

路由链接:

当安装配置了router,就可以使用router-link来替代普通的a链接进行跳转

首页电影关于首页电影关于

router-link中的 to属性,与a链接中的href属性相同,都是用来填写跳转的路径链接

router-link的to属性中的属性值,不需要写成 #/path,直接忽略#号,用/开头即可

2.2 redirect重定向

路由重定向 指的是: 用户在访问 地址A 的时候,强制用户跳转 到地址C,从而展示特定的组件页面。

通过路由规则的redirect属性,指定一个新的路由地址为 /,然后通过redirect重定向指向一个组件路由

//3、创建路由的实例对象const router = new VueRouter({//在路由的实例对象中//用一个 routes:[]数组,来定义 hash地址与组件之间的对应关系routes:[{path:'/',redirect:'/Home'},{path:'/Home', component:Home },{path:'/Movie',component:Movie},{path:'/About',component:About}]})

就是首次打开页面的时候,url访问的是 端口号/#/

但是没有组件声明的path路径是 /

所以打开页面没有进行路由跳转时候view是空白滴,所以就是打开的时候,/路径强制跳转到指定的组件路由路径

三、嵌套路由

1、模板内容中又有 子级路由链接

2、点击 子级路由链接 显示 子级模板内容

其实就是在App组件里面展示出来的路由组件内又绑定了其他的路由

3.1 声明子路由的规则

通过 children 属性声明 子路由规则

在index.js文件的路由实例中,在已声明的路由内,用children属性,以数组对象的形式,去声明在这个组件路由内的子路由规则。

举例

routes:[{path:'/About',component:About,children:[{path:'tab1',component:Tab1},{path:'tab2',component:Tab2},]}]})

注意:外层的路由的path属性值是有斜杠/开头的,其下的子路由是不用写/斜杠开头

子路由在该父路由内调用router-link和view即可

在父路由内嵌套link子路由的时候,需要在前面加上父路由的链接/父级/子级

3.2 默认子路由

在绑定了子路由以后,想要实现打开的时候,就默认展示某个子路由

方法:给父级路由重定向redirect:/父路由/子路由

默认子路由:如果children数组中,某个路由规则的Path值为空字符串,则这条路由规则叫做子路由

{path:'/About',component:About,children:[{path:'', //tab1的path为空,一进入About默认展示tab1component:Tab1},{path:'tab2',component:Tab2}

四、动态路由

4.1 动态路由的概念

动态路由指的是:把 hash地址中 可变的部分 定义为 参数项,从而 提高路由规则的复用性

(也就是说路由的path属性值是固定的,hash/(可变的部分),地址后面的可变的部分

在router中使用 英文的冒号( : ),来定义路由的参数项,如下

{path:'/Movie',component:Movie} //这里是访问Movie

但是,要访问Movie下的id值,就用 :参数项

{path:'/Movie/:id',component:Movie},

id作为一个动态传入的参数项

4.2 动态路由取参方式一(:参数项)

举例

在router的配置项中,给Movie的组件路由添加一个动态的id参数项,然后在访问该路由的时候,通过不同的id去访问到不同的数据

1、给Movie的配置项添加参数项

{path:'/Movie/:id',component:Movie},

2、给路由绑定链接,并传id值,希望通过id值来访问到不同电影的数据

大电影中电影小电影

3、此时如何通过Movie去获取到传递过来的id

打开Movie组件,当点击跳转传递了id后,测试打印组件的this

log出来的this是Movie组件的实例,打开找到一个 $route (不带r的) 的属性,指向的是一个object

其中有一个params对象,其中包含了一个id属性(这个id就是在路由path上定义的动态参数项id)

取值: this.$route.params.参数项

(其中this是可以省去不写的))

4.3 动态路由取参方式二(props传参)– 常用

(两种取参方式彼此独立)

该取参方法:给路由规则开启props传参

1、给组件添加一个 props:[],与methods和data平级

export default {name: 'Movie',props:[],methods:{showThis(){console.log(this);}}}

2、回到router/index的路由实例中,为该组件的路由添加props,并把值设置为true,表示为该路由开启props传参

{path:'/Movie/:id',component:Movie,props:true},

这里动态传了一个参数项id,然后开启props传值

3、回到Movie组件,在props数组中获取到参数值

props:['id'],

4、打印测试取值是否成功

//在结构上直接调用参数项id
{{id}}
//在行为上则是 this.参数项methods:{showThis(){// console.log(this);console.log(this.id);}}

4.3 动态路由 – query & fullPath

query传参取值

除了路径参数以外,还有查询参数

在hash地址中,在后面拼接 ” /> this.$route.query 来访问查询参数

大电影中电影小电影

这样子写,参数之间中间没有空格,属性值没有引号

然后去看组件的this,可以在route对象中找到query的属性

如果要获取到它的值,就是:this.$route.query

fullPath

当打开this,发现route对象上除了query和params以外还有一个fullPath和path

两者的区别:path不包含查询参数,fullPath包含了路径和查询参数,是一个完整的hash地址

如果需要用到完整路径,就是fullPath,不需要用到参数,就是path

五、编程式导航跳转

编程式导航跳转: push、replace、go

5.1 声明式导航 & 编程式导航

声明式导航:

  • 在浏览器中,点击链接 实现导航的方式,叫做 声明式导航,例如:

    • 普通网页中点击 链接,vue项目中点击 都属于声明式导航

    • 就是声明一个标签来进行跳转

编程式导航

  • 在浏览器中,调用js – API方法 实现导航的方式,叫做 编程式导航,例如:

5.2 vue-router中的编程式导航API

vue中最常用的编程式导航跳转: push、replace、go

  • this.$router.push(“hash地址”)

    • 跳转到指定的hash地址,并 增加 一条历史记录

  • this.$router.replace(“hash地址”)

    • 跳转到指定的hash地址,并 替换当前的 历史记录

  • this.$router.go(数值n)

    • n值可为负数和正数

    • 让当前页面前进/后退n步

    • 前进为+n

    • 后退为-n

    • 注意:如果后退的层数超过上限(-100等),则页面原地不动

$router.go的简化用法

  • 在实际操作中,一般只会前进和后退一层页,因此vue-router提供了两个便捷方法

    • $router.back()

      • 在历史记录中,页面后退一层

    • *$router.forward()

      • 在历史记录中,页面前进一层

  • 这种操作,只需要写在行内就可以了

    • 给后退按钮绑定点击事件,然后方法直接书写

六、导航守卫

6.1 什么是导航守卫

导航守卫 可以 控制路由的访问权限

例如:

在首页,点击导航进入后台主页,需求是在用户登录账号以后才可访问

但是,在未登录的情况下,是可以直接访问到Main后台主页的

就需要通过导航守卫来控制是否可以跳转

如果没有登录,访问main主页的话,就会强制跳转到登录页面

6.2 全局 前置 守卫

前置:从A跳到B的时候,还没有跳呢,就触发了前置导航守卫

每次发生路由的 导航跳转 时,都会触发 全局前置守卫,因此,在全局前置守卫中,可以对每个路由进行 访问权限 的控制:

声明全局前置守卫的方法

调用路由实例对象的 beforeEach 方法,即可声明:全局前置守卫

每次发生路由导航跳转的时候,都会自动触发 beforeEach(方法内的回调函数fn)这个fn回调函数

(在路由模块声名语法)

//调用 router.beforeEach()方法声明全局前置守卫router.beforeEach(fn)

beforeEach:在xxx之前

举例

//调用 router.beforeEach()方法声明全局前置守卫router.beforeEach(function(){​})

这个fn回调就是守卫方法,只要发生了路由的跳转,必然会触发这个fn回调

6.3 守卫方法的3个形参

全局前置守卫 的回调函数中接收了3个形参,格式为:

router.beforeEach(function(to,from,next){​})

三个形参:(从A跳转到B)

1、to:将要访问的路由的信息对象 (B方)

2、from:是将要离开的路由的信息对象(也就是A方)

3、next:是一个函数,调用 next() 表示旅行,允许本次路由导航,如果在fn里面不写 next(),那么全部的路由都不会实现跳转(因为在路由执行之前,先触发了fn回调,然后没有被放行)

6.4 next() 的三个调用方式

一、当前用户 拥有 后台主页的访问权限,直接放行:next()

二、当前用户 没有 后台主页的访问权限,强制跳转到指定(登录)页面: next(‘/login’)

三、当前用户 没有 后台主页的访问权限,不允许发生跳转,强制用户停留在当前页面(不给跳到后台主页):next(false)

6.5 控制访问权限

以上图举例实现

前置准备

1、创建两个组件:Main和Login,并为其添加路由规则

 { path:'/login',component:Login }, { path:'/Main',component:Main }

2、然后给一个HOME主页去绑定后台主页的路由

访问后台主页

3、这个时候在主页点击,是可以直接跳转到路由滴

问题:这个时候是没有登录滴,就需要进行控制

写法

在路由模块内声明前置守卫,但是不能直接放行,需要通过if去控制是否放行

分析:

1、要拿到用户将要访问的 hash 地址

2、判断 hash 地址是否等于 /main

2.1 如果等于 /main,说明需要登录之后才可以访问成功!

2.2 如果不等于 /main,就表示不需要登录,直接放行:next()

3、如果访问的地址是 /main,则需要读取 localStorage 中的 token 值

通过 localStoragec.getItem(‘token’)来获取到token值

(当用户第一次使用账号密码成功进行登录后,服务器便生成一个Token,所谓的Token,其实就是服务端生成的一串加密字符串、以作客户端进行请求的一个“令牌”)

3.1 如果有token,则放行

3.2 如果没有token,则强制跳转到/login 登录页

//调用 router.beforeEach()方法声明全局前置守卫router.beforeEach(function(to,from,next){console.log(to);console.log(from);if(to.path === '/Main'){//1、访问后台主页,需要判断后台是否有tokenconst token = localStorage.getItem('token')//3、如果token值存在,就表示已经登录if(token){next()}else{//4、没有登录,强制跳转到Login登录页next('/Login')}}else{//2、如果访问的不是后台,就直接放行了next()}})