> 文档中心 > 四、Vue之路由详解

四、Vue之路由详解


一、简介

Vue项目采用的是单页面应该(SPA),即整个应用只有一个页面,通过路由来在单页面中进行组件的切换,从而改变页面展示的内容,而不发生页面的跳转。

二、路由的使用

2.1 安装插件
路由是一个插件,首先要安装插件。默认安装的是vue-router4版本,对应的是vue3版本。这里使用vue2,所以要指定版本安装,安装vue-router3版本。

npm i vue-router@3

安装成功后,可以在package.json文件里看安装版本:
在这里插入图片描述
2.2 定义路由路径
在src下创建router文件夹,定义index.js,里面配置路由映射路径:

//该文件用于创建整个应用的路由器import VueRouter from 'vue-router'//引入组件,这里引入需要配置跳转路径的组件,这种组件也称为路由组件import HelloWorld from './components/HelloWorld.vue';import HelloHello from './components/Demo.vue';//创建一个路由器对象const router= new VueRouter({    routes:[//配置路由规则 {     path:'/HelloWorld', //组件的跳转路径     component:HelloWorld  //要跳转的组件 }, {     path: '/HelloHello',     component: HelloHello }    ]})//暴露路由器的对象export  default router;

2.3 Vue实例引入路由器
在main.js中,引入VueRouter和上述定义的router对象

//引入VueRouterimport VueRouter from 'vue-router'
//引入路由器import router from './router'

使用router插件:

Vue.use(VueRouter)

使用该插件后,Vue对象中,就可以定义router属性了,然后把暴露出来的router对象传进去。

//创建vmnew Vue({el:'#app',render: h => h(App),router:router})

2.4使用路由实现组件跳转切换
在切换组件的按钮处,用标签包裹,to属性写index.js里配置的路由路径。实现点击内容,切换组件的效果,如下:

<router-link to="/HelloWorld">Hello</router-link><br><router-link to="/HelloHello">Demo</router-link>

在展示内容区域,用占位,会自动在该区域展示组件内容:

 <router-view></router-view>

注意:一般称定义在中的组件为路由组件。一般把路由组件都放在pages文件夹下。非路由组件放在components文件夹下。

2.5 知识升华
当使用vue-router插件后,所有的组件实例里,包括路由组件和非路由组件,都会有$router属性和$route属性。
$route属性每个组件都存着自己组件的路由信息,每个组件各不相同,如下图:
在这里插入图片描述
里面有fullPath属性,meta属性,params属性和query属性等多个属性。
$router属性全局都是一个同样的对象,它就是管理路由的路由器对象。
在这里插入图片描述
切换组件时,默认情况下,每次被切换的组件都会被销毁,重新切换回该组件时,再重新创建该组件。

三、多级路由

当路由组件内部,也要切换路由时,可以在路由文件中配置多级路由。配置规则如下:
在这里插入图片描述
跳转路径时,从父级路径开始写全路径:

<router-link to="/home/news">News</router-link>

四、路由传参

上面讲到,在每个组件的$route属性中,都有query属性和params属性,这两个属性是用于在组件跳转时,携带参数,给跳转到的组件传递数据用的。
4.1 query传参
第一种写法:
的to属性中,在路由路径后面直接加?,然后拼接key=value&key=value传递参数,类似于get请求传参。当传递的参数用到组件中的数据时,需要在to前面加:,相当于v-bind的简写。但是加了冒号后,to里面的全部内容都会当成js表达式来解析,而url的路径不是js表达式,这么写肯定会报错。所以需要用分隔符`来包裹url数据,然后用${}来获取组件中的数据,写法如下:
四、Vue之路由详解
这样,切换到的组件的route属性的query里面,就有router-link中传递过来的参数了。
在这里插入图片描述
第二种写法:
router-link标签的to属性,写成对象的形式,如下:
在这里插入图片描述
写成对象的形式,path属性写路由的路径,query属性写传参。除了使用path属性外,还可以定义name属性,来与路由组件进行映射,此时,index.js的路由配置里也要写name属性。
需要注意的是,to属性写成对象后,query里的参数就无需写占位符了,直接写组件属性即可。
接收到数据后,vc实例就可以通过route.query.xxx来获取值了。

4.2 params传参
使用params传递参数,类似于resultful风格的url进行参数传递。
首先,在router/index.js里的路由路径里,写参数占位符,如下:
四、Vue之路由详解

中传参时,用RestFul风格传参。如下:
在这里插入图片描述
注意:给params传参时,to属性里写成对象时,必须用name属性映射路由,不能用path属性映射

切换到组件后,组件的$route.params里就有参数了。
props属性
在配置params传参的配置文件中,可以配置props属性,这样,在接收参数的组件中,通过props属性就可以直接调用参数属性获取值了,无需再写复杂的route.params获取参数了,props配置如下:
在这里插入图片描述

五、路由的其他特性

5.1 的replace属性
当路由组件进行切换时,浏览器默认把上一个组件当成了历史记录,点返回键,会调到上一个切换的组件页面,称之为push模式。如果不想跳到上一个组件中,那么把该组件的router-link的属性设置为true。浏览器就不会记录这个地址,也不会返回这个组件,而是返回上一个replace为false的组件中去。
在这里插入图片描述

5.2 编程式路由
所谓编程式路由,就是不通过router-link标签进行组件的切换,而是通过代码方式进行组件切换。
在这里插入图片描述

5.3 缓存路由组件
上面讲到,当切换组件时,被切换的组件会被销毁,每次切换,都涉及到组件的销毁和重新创建,如果不想让组件重新销毁,比如用户在组件中输入了一些数据,等切换回来时,这些数据还要在页面保留,那么就不能进行销毁。
需要进行特殊的设置,即在占位符处,用标签包裹。用include属性设置不被销毁的组件,写组件name属性。
一个组件时:
四、Vue之路由详解
多个组件时:
四、Vue之路由详解

5.4路由组件独有的两个生命周期
路由组件有两个新的生命周期,
activated:路由组件被激活时触发
deactivated:路由组件失活时触发。

5.5 路由的meta属性
在路由配置文件index.js中配置路由时,可以设置meta属性,来自定义一些信息。通常自定义一些标识信息,然后在路由守卫中,获取这些标识,进而判断是否放行等操作。
5.6 路由的hash模式和history模式
路由配置中,可以配置mode属性,默认是hash模式,这种模式下,浏览器的地址栏中,会有#。#后面的路径,都是vue项目内部跳转的路径,其不会传到服务器后台,#及#后面的路径,称之为hash路径。
mode属性可以设置为history,这样,浏览器地址栏中就没有#了。这种模式的弊端是,vue内部跳转的路径,也会发送给服务器后台,这样就会造成后台服务器返回404错误,因为vue内部跳转的路径,后台服务解析。这就需要后台服务进行一些处理了。

六、路由守卫

相当于访问某个路由组件时,给路由组件加了一个拦截器,这个拦截器就叫守卫。
全局前置守卫
在访问每个路由前,执行的一段代码,写法如下:
在router/index.js里,定义完router对象后,定义beforeEach函数:

// 前置路由守卫(路由导航)router.beforeEach((to, from, next) => {     console.log('to:', to)     console.log('from:', from)    if (to.path == '/home') { console.log('做逻辑判断')    }    // 下方这个next是适配所有路由的,放行操作,如果没有next,则会卡住,不会跳转进路由组件    next()})

beforeEach函数的调用时机:初始化时调用一次,以及每次路由切换时,调用一次。
全局后置守卫
在router/index.js里定义完router对象后,调用afterEach函数,定义全局后置守卫:

// 进入路由后方法勾子router.afterEach((to, from) => {    console.log(to, '后置第一个参数')    console.log(from, '后置第二个参数')    /*      to 目标路由      from 源路由    */    if (to.meta.title) { console.log(to.meta.title);    } else { console.log('暂无名称');    }});

调用时机:初始化时调用一次,以及每个路由切换后,调用一次。
后置全局路由不用放行,没有next参数。

独享守卫
写在路由配置文件的某个组件内,而不是写在router定义完后。与前置守卫类似,但是只拦截某一个路由。

{     path: '/HelloHello',     component: HelloHello,     beforeEnter(to,from,next){  if(to.path==="/test"){      alert("请登录");      next(false); // 禁止跳转  }else{      next()  }     } }

独享守卫只有前置拦截,没有后置拦截。

组件内守卫
不在路由的js里写,而在组件内部写的路由,包括beforeRounterEnter和beforeRouterLeave属性
通过路由规则,进入该组件时调用和通过路由规则,离开该组件时被调用。
与上述讲到的activated和deactivated类似,不同的是,组件内守卫必须通过路由规则进入时才会进入beforeRounterEnter和beforeRouterLeave,而直接写组件标签调用的方式进入组件不会走这两个方法。