1.下载
使用命令npm i vue-router
下载;
2.使用
在src
文件夹下,创建一个router
文件夹,里面创建一个index.js
文件,里面存放路由的配置信息;
[1]注册
import Vue from 'vue'
import VueRouter from 'vue-router'
// 全局导入,本质将VueRouter挂在到Vue的原型对象上
Vue.use(VueRouter)
[2]实例化路由对象
const router=new VueRouter(options)
- options为配置项,值为一个对象
配置项
mode
mode表示路由模式,常使用的layout模式有两种,一种是hash
、一种是 history
。两者的具体使用及区别如下->传送门
routes
routes用来配置路由信息,值为一个数组,数组的每个元素为一个路由映射规则。
语法
[
{
path:'路径',
component:组件名
}, // 添加一条路由
{
path:'路径',
redirect:'新路径'
}, // 路由重定向-->也就是说若是输入的是路径,自动跳转到新路径页面
{
path:'路径',
component:组件名,
children:[
{...子路由}
] // 嵌套路由
}
...
]
- 属性总结
- path:路径
- redirect:重定向路径
- component:组件名
- children: 子路由的配置项
(1)配置路由-添加一条路由
import index from './index'
const routes = [
{path:'/index', component:index}
]
const router = new VueRouter({routes})
(2)配置路由-嵌套路由的使用
-
需求场景:仅需修改组件下的某部分,并不需要修改整个页面;
-
步骤
- 1.在想要使用嵌套路由的组件中加一个路由出口;
- 2.配置该路由的
children
属性(是一个数组
)
-
语法
- 在children中的配置项与routes中一致;
- 需要注意的是->嵌套路由的路径
- 嵌套路由的路径有两种写法->
加父路径加/,不加父路径不加/
- eg: 在home页面嵌套路由company,其路径
- 写法1: 直接写company 不加/
- 写法2 写全 /home/company
- 嵌套路由的路径有两种写法->
-
举例说明
{ path:'/test', component:test, // 默认展示 test1组件的内容 redirect:'/test/test1', children:[ {path:'test1',component:test1}, {path:'test2',component:test2}, {path:'test3',component:test3}, ] },
<template> <div> <div> 我是不修改部分 <router-link to='/test/test1'>底部为第一部分</router-link> <router-link to='/test/test2'>底部为第二部分</router-link> <router-link to='/test/test3'>底部为第三部分</router-link> </div> <router-view></router-view> </div> </template>
-
嵌套路由传参-通过router-view进行传参
<!-- 父组件-路由出口 --> <router-view 参数名='参数值'></router-view>
// 子组件 props:{ 参数名:{ type:希望参数类型 } }
(3) 配置路由-路由重定向
有时我们希望用户输入某个路径时,自动跳转到另一个路由中,比如用户输入域名(不带路径)
const routes = [
// 当用户没有输入路径时会自动跳转到登录页
{path:'/', redirect:'/login'}
]
(4)配置路由-路由别名
1.语法–配置路由时
{
path:'路经',
component:导入的组件,
meta:{路由元信息},
alias:‘路由别名(另一个可以访问此网页的路经路经)’
}
2.使用
[1]在项目中,一般我们将’/‘路由重定向为’/login’,
{
path:'/',
redirect:'/login'
}
----此时也可以给登录界面起一个别名
{
path:'/login',
alias:'/',
component:()=>import('login.vue')
}
(5)配置路由-路由元信息
1.定义:路由元信息其实就是在路由配置
的时候给它设置一些额外信息;
2.语法
{
path: '/login',
component: Login,
// ---增加一个meta属性(是一个对象),里面存放配置路由时的额外信息
meta:{
metaPath:'/login',
title:'登录界面',
}
}
3.举例说明-使用路由元信息修改网页标题
其实我们可以在每个路由页面created钩子中去修改页面的标题,但是非常的麻烦,若是页面多的话,每个页面都要写created函数去修改;
在这里我们使用路由后置导航首位+路由元信息去获取修改网页标题,代码如下
# 在配置路由的时候,在路由元信息中添加标题
const routes = [
// 一个对象代表一个映射规则
{
path: '/login',
component: login,
meta: {
title: '登录界面'
}
},
{
path: '/',
redirect: '/login'
},
{
path: '/layout',
redirect: '/layout/question',
component: layout,
children: [
{
path: '/layout/echart',
component: echart,
meta: {
title: '数据列表'
}
},
{
path: '/layout/user',
component: user,
meta: {
title: '用户列表'
}
},
{
path: '/layout/subject',
component: subject,
meta: {
title: '学科列表'
}
},
{
path: '/layout/question',
component: question,
meta: {
title: '题库列表'
}
},
{
path: '/layout/enterprise',
component: enterprise,
meta: {
title: '企业列表'
}
}
]
}
]
# 2.在路由后置导航守卫中,(to是代表当前进入页面的路由信息)通过to.meta.title获取我们为当前页面设置的标题,并设置到document.title。innerHTML中
router.afterEach(to => {
// 给网页添加标题
document.title = to.meta.title
})
(6)配置路由问题-共享组件将不会重新渲染
我们有时候开发中会把多个路由解析为同一个Vue组件。问题是,Vue默认情况下共享组件将不会重新渲染,如果你尝试在使用相同组件的路由之间进行切换,则不会发生任何变化,此时我们需要传递key来区分,达到刷新的目的
const routes = [
{
path: "/a",
component: MyComponent
},
{
path: "/b",
component: MyComponent
},
];
<template>
<router-view :key="$route.path"></router-view>
</template>
路由独享守卫-beforeEnter
语法
路由独享守卫是指在单个路由配置的时候也可以设置的钩子函数,语法如下:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
// 只有调用next函数才会进行路由跳转
}
}
]
})
使用时机
什么时候才会使用到此钩子函数呢?
情况1: 当前项目的页面为推广页面,用户通过推广链接进入某页面。而大部分页面在进入时需要获取初始化信息,可以将这些逻辑提取在beforeEnter
中,那个页面需要获取在路由中进行配置;
情况2:某些页面进入之前需要进行检测是否有权限,可以在此进行配置
[3]导出实例化对象
// 由于我们在入口文件中需要将路由对象挂在到根实例中,所以在此处需要导出(此处使用的默认导出)
export default router;
[4]在入口文件中引入路由,并将路由实例化对象挂在到根实例中
-
//导入路由 import router from '@/router/index.js'; new Vue({ //挂载路由 router, render: h => h(App), }).$mount('#app')
-
[5]路由出口
-
在
App.vue
主组件中路由出口–相当于占位符,那里使用写哪里; -
<router-view></router-view>
-
[5]检查路由配置成功
检查路由是否配置成功,可以在App.vue中写一个点击看是否报错;
一般不报错说明我们配置的路由是正确的!
3.路由的两种导航方式
[1]router-link
-
<router-link to='路经'></router-link>
-
router-link 是已经全局注册过的自定义组件,支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 a 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名
-
优点:可以使Vue Router在
不重新加载页面
的情况下更改URL,处理URL以及生成编码; -
属性
-
to:表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象
-
replace:属性值为boolean值,默认为false;若是值为true,当点击时,会调用 router.replace() 而不是 router.push(),跳转后不会在 history 留下记录
-
event:声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组
-
<!-- 表示该链接在鼠标hover的时候触发--> <router-link to='/test/test2' event='mouseover'>底部为第二部分</router-link>
-
-
active-class:设置 链接激活时使用的 CSS 类名;
-
tag:有时候想要 router-link 渲染成某种标签,例如 < li v-pre>,可以使用tag属性 tab=‘li’;
-
可以通过query,params携带参数;
-
-
[2]$router
-
2.使用router的实例方法来实现
- 在某个组件中
this.$router.push('路经')
$router.push('路经')
- 在js中
- 导入router
router.push('路经')
- 在某个组件中
4.$router
与$route
的区别
总的来讲$router是用来操作路由的, $route是用来获取路由信息的
$router
$router是VueRouter的一个实例,他包含了所有的路由信息及功能,包括路由的跳转方法,钩子函数等,也包含一些子对象;
[1]options属性
- $router的options属性是创建 Router 时传递的原始配置象,是只读的;
- mode:模式;
- routes:创建路由实例化对象时传递的参数routes;
[2]currentRoute属性
- currentRoute:当前路由信息(等同于当前页面的$route)
[3]路由传参
(1)query路由传参
query传参方式是将参数拼接在路由url上进行传参;
-
语法1(简写)
-
this.$router.push('路由url?参数名1=参数值1&参数名2=参数值2')
-
-
语法2
-
this.$router.push({ path:'路由url', query:{ 参数名1:参数值1 参数名2:参数值2 ... } })
-
-
接收
-
参数会存入到当前路由信息中,也就是说
$route
或$router.currentRoute
中都可以获取到-
// 当前页面$route this.$route.query 为一个对象,可以通过点语法或[]语法获取指定参数
-
-
-
特点
- [1]query方式传参是拼接在url上进行传参的,
- 因此刷新页面数据不会丢失;
- 接收到的数据都是字符串类型,若是需要其他类型需要自行转化;
- [2]query是使用path或name进行传参的;
- [1]query方式传参是拼接在url上进行传参的,
(2)params路由传参
params路由传参是配合路由name属性进行传参
-
语法
-
配置路由name属性
-
{path:'路由url', component:组件, name:'组件名'}
-
-
传参
-
this.$router.params({ name:'路由名', params:{ 参数名1:参数值1 参数名2:参数值2 ... } })
-
-
接收
-
参数会存入到当前路由信息中,也就是说在
$route
或$router.currentRoute
中都可以获取到-
// 当前页面$route this.$route.params 为一个对象,可以通过点语法或[]语法获取指定参数
-
-
-
特点
- 页面刷新数据就会丢失;
- 只能配合name属性进行传参;
-
(3)动态路由匹配
-
语法
-
[1]配置路由参数
-
// 这样写相当于当前路由必须携带参数,否则进入不了当前页面 {path:'路由url/:参数名', component:组件} //这样写加不加参数都可以跳转到当前页面 {path:'路由url/:参数名?', component:组件}
-
-
[2]传参:跳转路由时传参(大部分是用于传递一些id之类的–不能使用数组/对象/中文字符)
-
this.$router.push('路径/参数值')
-
-
[3]获取-在相应路由对应的组件获取
-
this.$route.params.参数名
-
-
注意
- 在url中也有体现,并且刷新数据不会丢失;
-
[4]导航守卫
[1]全局前置守卫
1.作用:
只要是路由跳转,无论是编程式导航($route.push(‘路径’))或者是手动输入都会跳转到该回调函数中;
全局前置导航守卫就是拦截路由跳转并做一定的判断!
还没有跳转到相应的路由页面!
2.语法
# 实例化对象router.beforeEach(参数是一个异步回调函数)
router.beforEach((to,form,next)=>{
# to 到哪里去(里面存储了要跳转的 ·路由信息·)
// ----path属性存储了跳转的路径(不包含参数 eg:'/layout')
//-----fullPath属性存储了跳转的路径(包含参数)
# form 从哪里来(里面存储了跳转之前的 ·路由信息·)
# next回调函数(决定:能不能跳转,跳转到那里去)
//------若是没有写next,页面会卡死(因为不知道你能不能跳转跳转到那里去)
#若是允许跳转next();
#若是不允许,跳到别的地方next('新路径');
})
3.举例说明
在每次进行路由跳转的时候判断存不存在token
//eg:路由每次跳转之前判断有没有token,若是有允许跳转,若是没有跳转到登录界面
if(to.path==='/login'){
//直接跳转
next();
}else {
//判断是否携带了token
let token=getToken();
if(token){
//若携带的是token
next();
}else{
//不携带就跳转到登录界面
next('/login');
}
}
[2] 全局解析守卫
beforeResolve这个钩子和beforeEach类似,也是路由跳转前触发,参数也是to、from、next三个。
和beforeEach区别为:在 beforeEach 和 组件内 beforeRouteEnter 之后,afterEach之前调用。
[3]全局后置导航守卫
1.作用:
当执行完路由跳转之后执行的钩子;
已经跳转到相应的路由(页面)
2.语法
router.afterEach((to, from) => {
# to中存储了当前页面的 ·路由信息·
//-------fullPath(全路径)
//-------path(路径)
--------------------区别:全路径携带参数,路径不携带参数
//params----params类型的参数
//query=---query类型的参数
--------------------
//meta:路由元信息
#----就是在路由配置的时候给它设置一些额外信息;
#----若是没有额外信息,to.meta是一个空的对象
})
3.举例说明—使用后置守卫设置路由标题
/权限控制---路由后置守卫
router.afterEach(to => {
window.document.title= to.meta.title;
})
#修改标题window.document.title='值'
[4]组件内-组件前置守卫
在还没有进入该组件之前触发,在渲染该组件的对应路由被confirm前调用,此时不能获取组件实例 this,因为当守卫执行前,组件实例还没被创建,但是可以通过传一个回调给next来访问组件实例,在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数,即上文参数中提到的next((vm)=>{})。
beforeRouteEnter: function(to, from, next) {
// 若是想获取实例对象及数据,可以在next回调函数中获取
next(vm=>{
})
}
[5] 组件内-组件更新守卫
组件更新守卫在动态路由中使用,由于动态路由中切换路由的时候,由于绑定的是同一个组件因此在不会在重新渲染,但是为了可以让组件中的内容重新渲染,有两种方法第一种使用watch监听,这种需要使用props写法,另一种就是在beforeRouteUpdate中定义,其会监听到动态路由的改变,因此可以在这个钩子中获取异步动态路由对应的数据,举例来说,对于一个带有动态参数的路径/example/:id,在/example/1和/example/2之间跳转的时候,由于会渲染同样的Example组件,因此组件实例会被复用,而这个钩子就会在这个情况下被调用,在这个钩子函数中可以访问组件实例 this。
beforeRouteUpdate: function(to, from, next) {
// ...
}
[6] 组件内-组件离开守卫
导航离开该组件的对应路由时调用,可以访问组件实例this,这个离开守卫通常用来禁止用户在还未保存修改前突然离开,该导航可以通过next(false)来取消。
beforeRouteLeave: function(to, from, next) {
// ...
}
to与form中存在的参数(路由信息
)
- fullPath:全路径(带参数)
- path:路经(仅包含路经,不带参数)
meta
:路由元信息- params:参数
- query:参数
- name:组件名
- hash:哈希值
示例-利用导航守卫给路由跳转加进度条
进度条插件
nprogress
(progress是进度的意思)
在vue中使用步骤:
- 1.下载包:npm i nprogress
- 2.导入:
- 导入js import Nprogress form ‘nprogress’
- 导入css import ‘nprogress/nprogress.css’
- 3.使用其方法
- 进度条开始: Nprogress.start()
- 进度条结束: Nprogress.done()
- 注:我们一般在导航守卫中使用·
- 前置导航守卫—Nprogress.start()
- 后置导航守卫— Nprogress.done()
- 注意点:
- 不要加定时器,容易造成网站卡死的假象!
$route
$route就是存储了当前路由的配置信息
4.解决路由重复跳转的错误
路由重复跳转的问题
若是在当组件又跳转到当前组件就会报错;
—直接复制错误,搜索复制即可;
// 就是在路由的原型上加上.catch方法
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location) {
return originalPush.call(this, location).catch(err => err)
}