VueRouter的使用
Vue-Router 的安装和配置
首先,对一个项目而言,我们需要对VueRouter分文件进行统一管理。一般来说,我们会在项目的src目录下创建一个router文件夹,在router文件夹下分别创建两个基本文件,index.js和router.js。
-src
-router
index.js //存放router的基本配置
router.js //存放routes的信息
// router 下的index.js 基本配置
import Vue from 'vue' //引入Vue对象,为了方便注册VueRouter
import VueRouter from 'vue-router' //引入VueRouter,方便new一个新的对象
import routes from './router' // routes是我们配置路由的相关信息,这里也引入进来做初始化
Vue.use(VueRouter) //注册路由
const router = new VueRouter({
routes //将routes 的路由配置信息放到创建的路由对象中
})
export default router //导出router对象,该router对象会在main.js中被赋值到vue实例中去
// router 下的 router.js基本配置信息
const Home = () => import('@/views/Home') //路由懒加载
const About = () => import('@/views/About') //路由懒加载
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
export default routes //导出 routes对象,在index.js里面 引入
Vue-Router的路由懒加载
路由懒加载的目的是为了减少首次进入页面的请求时间,使用户看到首页速度更快。
路由懒加载会根据你的设置将打包的js文件分割成若干个小js,按照路由跳转的需求按需加载,跳转到哪个路由地址,就加载哪个地址的js文件。
// 路由懒加载的使用介绍
// router.js文件中
const Home = () => import('@/views/Home') //路由懒加载
const About = () => import('@/views/About') //路由懒加载
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
export default routes //导出 routes对象,在index.js里面 引入
Vue-Router的嵌套路由
嵌套路由就是在一个被路由过来的页面下可以继续使用路由,嵌套也就是路由中的路由的意思。
比如在vue中,我们如果不使用嵌套路由,那么只有一个<router-view>,但是如果使用,那么在一个组件中就还有<router-view>,这也就构成了嵌套。
// router.js文件
const Home = () => import('@/views/Home') //路由懒加载
const About = () => import('@/views/About')
const Parent = () => import('@/views/Parent')
const Child = () => import('@/views/Child')
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
// 这里要注意,children后面的path 一定不要加/,不然还是会解析为根目录的路由
{
path: '/parent',
name: 'Parent',
component: Parent,
children: [
{
path: 'child',
component: Child
}
]
}
]
export default routes
Vue-Router的命名路由
给一个路由命一个唯一的名称,主要用在标签<router-link>中,可以通过标签的to属性跳转到指定命名路由。在后续的路由守护、重定向等里面也都可以用到命名路由。
// router.js文件
const Home = () => import('@/views/Home') //路由懒加载
const About = () => import('@/views/About')
const Parent = () => import('@/views/Parent')
const Child = () => import('@/views/Child')
const routes = [
{
path: '/',
name: 'Home', //这种就是命名路由
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
// 这里要注意,children后面的path 一定不要加/,不然还是会解析为根目录的路由
{
path: '/parent',
name: 'Parent',
component: Parent,
children: [
{
path: 'child',
name: 'child',
component: Child
}
]
}
]
export default routes
// 在parent.vue文件中
// 通过router-link 标签中的to属性和v-bind的绑定使用,我们可以通过命名路由来实现跳转,而不需要传path路径
<template>
<div>
this is parent
<router-link :to="{name: 'child'}">child</router-link>
<router-view></router-view>
</div>
</template>
Vue-Router命名视图
命名视图一般使用在需要多个路由视图中,例如一个vue页面中需要展示三个不同的<router-view>这时候就必须使用命名视图来达成效果,一般来说命名视图用来做布局用
// router.js文件
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const Parent = () => import('@/views/Parent')
const Header = () => import('@/views/Header')
const Right = () => import('@/views/Right')
const Left = () => import('@/views/Left')
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
// 在parent页面中通过children子路由实现命名视图
{
path: '/parent',
name: 'Parent',
component: Parent,
children: [
{
path: '',
components: {
default: Header,
left: Left,
right: Right
}
}
]
}
]
export default routes
// 在parent.vue中
<template>
<div>
this is parent
<router-view></router-view>
<router-view name="left"></router-view>
<router-view name="right"></router-view>
</div>
</template>
Vue-Router 重定向
重定向是重新设置当前路由功能,比如我们可以讲/重定向到/home以防止用户手动通过/来访问,可以让这两个路由目标地址保持一致
// router.js文件
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const Parent = () => import('@/views/Parent')
const Header = () => import('@/views/Header')
const Right = () => import('@/views/Right')
const Left = () => import('@/views/Left')
const routes = [
{
path: '/home',
name: 'Home',
component: Home
},
// 这三种写法都可以实现redirect重定向,一般来说redirect是为了防止用户通过修改url路径直接访问路径
{
path: '/',
// redirect: { name: 'Home' }
// redirect: '/home'
redirect: to => {
return { name: 'Home' }
}
},
{
path: '/about',
name: 'About',
component: About,
redirect: to => {
return { name: 'Home' }
}
}
]
export default routes
Vue-Router别名
给路由取别名可以更加方便的访问路由,不需要受限于繁杂的路由嵌套地址,一个别名可以顶替冗长的地址,使用起来更加方便。
// router.js文件
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const Parent = () => import('@/views/Parent')
const Header = () => import('@/views/Header')
const Right = () => import('@/views/Right')
const Left = () => import('@/views/Left')
//这里的alias就是别名,如果path的路径长度很长,这时候别名看起来就比较清爽了
const routes = [
{
path: '/home',
name: 'Home',
component: Home,
alias: '/winter'
}
]
export default routes
Vue-Router的编程式导航
在.vue中可能需要用户通过连接手动的跳转页面,这时候就需要编程式导航的方式来实现手动页面跳转,其中push是跳转到指定的路径,back是返回上一次的路径,forward是前进到返回之前的路径,replace是替换当前路径,注意replace不会留下跳转记录,因此无法通过back、forward返回,而push会留下记录。
// 编程式导航
<template>
<div>
this is parent
<button @click="handleClick('push')">跳转到首页</button>
<button @click="handleClick('back')">后退</button>
<button @click="handleClick('forward')">前进</button>
<button @click="handleClick('replace')">替换当前路径</button>
</div>
</template>
<script>
export default {
name: 'Parent',
methods: {
handleClick (type) {
switch (type) {
case 'push' :
this.$router.push('/')
break
case 'back' :
this.$router.back()
break
case 'forward':
this.$router.forward()
break
case 'replace':
this.$router.replace('/about')
break
default:
break
}
}
}
}
</script>
编程式导航我们可以传params或者query给目标路由,传query的时候,会在url最后的位置加上?name=thisisquery类似这种内容,目前路由可以通过$route.query.name来获取传递的信息。如果传递的是params,一定要注意path和params不能一起用,path会导致params失效。params可以通过$route.params.name来获取
// 传query
<script>
export default {
name: 'Home',
methods: {
handleClick () {
console.log(this.$route)
this.$router.push({
// name: 'Home'
path: '/home',
query: {
name: 'thisisquery'
}
})
}
}
}
</script>
// 传params
// params不能与path一起使用,path会导致params失效
<script>
export default {
name: 'Home',
methods: {
handleClick () {
console.log(this.$route)
this.$router.push({
name: 'Home',
params: {
name: 'woshilisi'
}
})
}
}
}
</script>
Vue-Router组件传参
路由也可以使用组件的props传参,只要设置props: true属性即可,需要在组件使用props属性接受路由传递的参数,在路由设置里面还有其他两种设置props方式,分别是对象模式、函数模式。
// 路由的props三种方式
// 布尔值方式
// router.js文件中的route配置里面
// 一定要注意path后面要加上:属性名
{
path: '/about/:name',
name: 'About',
component: About,
props: true
}
//对象模式 要注意对象模式的path中没有:name
{
path: '/about',
name: 'About',
component: About,
// props: true
props: {
name: 'morenzhi'
}
}
//函数模式 要注意函数模式中path没有:name,并且函数模式只能通过query传值
{
path: '/about',
name: 'About',
component: About,
props: (route) => ({
name: route.query.name
})
}
// 在.vue文件中
export default {
name: 'About',
props: {
name: {
type: String,
default () {
return '没有值'
}
}
}
}
Vue-Router HTML5 History模式
History模式需要浏览器的支持,VueRouter的默认模式是hash,在url中有#存在,实际项目中一般用History模式,但是需要注意,History需要后端支持,因为一旦url路径不匹配很容易就报错,因此需要后端支持。
// 路由index.js文件中
export default new Router({
mode: 'history',
routes
})
Vue-Router 导航守卫
VueRouter中的导航守卫,本质上就是钩子函数。它可以在实现跳转的时候做一个相关操作,比如导航拦截,重定向到登录页面等等操作,导航守卫相关的总共七个函数,分布在:路由本身,某个具体路由内部,组建内部。
// 导航守卫
// index.js 文件
// to 是失效页面的url
// from 激活页面的url
// next 执行下一步,如果不调用next,本次页面跳转不执行,必须调用next
router.beforeEach((to, from, next) => {
console.log('to:')
console.log(to)
console.log('from:')
console.log(from)
next()
})
//后置导航钩子
router.afterEach((to, from) => {
console.log('后置导航钩子')
})
//全局解析守卫
router.beforeResolve((to, from, next) => {
console.log('全局解析守卫')
next()
})
// 路由独享守卫
// router.js中
{
path: '/about',
name: 'About',
component: About,
props: (route) => ({
name: route.query.name
}),
// 一般在这里可以判断目标从哪个路由过来,防止用户手动通过输入路由地址跳转
beforeEnter: (to, from, next) => {
console.log('路由独享守卫')
if (from.name === 'Home') {
next()
} else {
next('/')
}
}
}
// 组件内的路由守卫
// 要注意,在beforeRouteEnter里面无法使用this获得当前组件对象,因为此时当前组件还没有渲染成功
<script>
export default {
name: 'About',
props: {
name: {
type: String,
default () {
return '没有值'
}
}
},
beforeRouteEnter (to, from, next) {
console.log('组件内导航守卫')
next(vm => {
console.log(vm.name)
})
},
//一般来说,beforeRouteLeave 可以用来做确认离开信息,可以通过next(false)取消当前页面跳转
beforeRouteLeave (to, from, next) {
console.log('组件内离开导航守卫')
next()
},
// 组件没有被销毁,当前路由更新的时候会进入
beforeRouteUpdate (to, from, next) {
console.log('组件内更新守卫')
next()
}
}
</script>
完成的流程:
1: 导航被触发
2:在失活组件中调用离开守卫 beforeRouteLeave
3:调用全局的前置守卫beforeEach
4:在复用的组件里调用 beforeRouteUpdate
5:调用路由独享守卫beforeEnter
6:解析异步路由组件
7:在被激活的组件里调用beforeRouteEnter
8:调用全局解析守卫beforeResolve
9:导航被确认
10:调用全局的afterEach后置勾子
11:触发DOM更新
12:用创建好的实例调用beforeRouterEnter守卫里面的next回调函数
Vue-Router路由元信息
//router.js文件中的代码
{
path:"/test",
name:"test",
component:()=>import("@/components/test"),
meta:{
title:"测试页面", //配置title
keepAlive: true //是否缓存
}
}
//index.js中的代码 设置title
router.beforeEach((to,from,next)=>{
if(to.meta.title){
document.title=to.meta.title
}
next()
})
<!-- app.vue中的代码 -->
<!-- 需要被缓存的路由入口 -->
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<!-- 不需要被缓存的路由入口 -->
<router-view v-if="!$route.meta.keepAlive"></router-view>