系列文章链接
目录
根据前面的流程,在新建vue项目的因为选择了默认安装vueRouter,所以项目里会有一个叫 router 的文件夹,里面有一个 index 的ts文件,系统里如果有新增需要跳转的页面,就需要在这个文件里进行配置。某种程度来说,这个文件的路由结构也反映了整个系统的结构。接下来进入正题~
组件注册
组件注册有两种方式,一是通过import引入组件,二是采用懒加载的方式。
import引入
import Login from '@/views/Login.vue';
const routes: Array<RouteConfig> = [
{
path: '/',
name: 'Login',
component: Login
}
]
虽然直接通过import引入,感官上会更直接,但是webpack在打包的时候会把整个路由打包成一个js文件,如果页面非常多就会导致这个文件非常大,从而导致页面加载缓慢。
懒加载-动态import(官方推荐)
懒加载就是将不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样可以提升SAP单页的加载速度。
嵌套路由
嵌套路由就是父路由里面嵌套他的子路由,父路由有自己的路由导航和路由容器(router-link、router-view),通过配置children可实现多层嵌套。
使用场景
在后台管理系统中,有用户模块,用户模块下面设有用户管理、角色管理等子模块。路由的配置的层级关系就像是盒子模型,大盒子是用户模块,子盒子1和子盒子2分别是大盒子里面的小盒子。
import Login from '@/views/Login.vue';
const routes: Array<RouteConfig> = [
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/home',
name: 'Home',
component: () => import('../views/Home.vue'),
children: [
{
path: '/users/user',
name: 'User',
component: () => import('../views/users/User.vue')
},
{
path: '/users/roles',
name: 'Roles',
component: () => import('../views/users/Roles.vue')
}
]
}
];
<template>
<el-menu :default-active="actived" class="el-menu-vertical-demo">
<template v-for="item in menuList">
<template v-if="item.children">
<el-submenu :index="item.path">
<template>
<span>{{item.meta.title}}</span>
</template>
<el-menu-item v-for="childItem in item.children" :index="childItem.path" @click="jumpRoute(item)">{{childItem.meta.title}}</el-menu-item>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.path" @click="jumpRoute(item)">
<template>
<span>{{item.meta.title}}</span>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
重定向redirect
简单来说重定向就是本来A页面打算跳转到B页面,但是由于B页面写了重定向到C页面,所以最后是从A页面到了C页面。
使用场景
就拿上面的用户模块来说,登录系统后希望跳转到用户管理页面,但是用户模块只是一个中转站,不存在任何实体页面,这个时候就需要在用户模块写一个重定向到用户管理页面到配置参数。
const routes: Array<RouteConfig> = [
{
path: '/home',
name: 'Home',
redirect: '/users/user',
children: [
{
path: '/users/user',
name: 'User',
component: () => import('../views/users/User.vue')
}
]
}
];
配置参数meta
在定义路由的时候可以配置meta字段,它可以在路由地址和导航守卫上都被访问到。
const routes: Array<RouteConfig> = [
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: {
title: '首页',
icon: 'el-icon-s-home',
isHeader: true
}
}
]
通过配置的title和icon,可以根据路由地址动态显示菜单的标题和图标,还可以通过isHeader来控制当前页面是否显示头部导航栏组件。通过meta里的自定义字段还可以进行路由或菜单的权限设置。
导航守卫
导航守卫主要用来通过跳转或取消的方式守卫导航。我们先来看看整个导航解析的流程,就清楚在不同的阶段会进行哪些操作。
全局前置守卫before
可以在router的index页面进行全局守卫配置。
//用户未能验证身份时重定向到/login
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
每个守卫会默认接受两个参数:
to :即将要进入的目标
from :当前导航正要离开的路由
还有一个可选的参数 next ,当导航守卫传递第三个参数next的时候,必须确保 next 在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。
全局后置钩子afterEach
和守卫不同的是,这些钩子不会接受next函数。由于这个阶段已经挂载实例,可以获取组件实例this数据,并且不会改变导航本身,主要适用于分析判断、修改标题、页面声明等辅助操作。
路由独享守卫beforeEnter
可以在路由配置页面,给某一个路由配置守卫,只有在进入该路由的时候才会被触发。
const routes: Array<RouteConfig> = [
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home.vue'),
beforeEnter: (to, from) => {
// reject the navigation
return false
}
}
]
离开守卫beforeRouteLeave
用于离开该组件前,页面还未被保存,可通过返回的false取消该操作。写在组件内,与生命周期使用的方法属于同级,而且需要引入 Component.registerHooks(['beforeRouteEnter', 'beforeRouteLeave', 'beforeRouteUpdate'])
使用场景
- 表单填写中,突然点了返回按钮,希望弹出警告框提示是否离开,选择离开或停留。
- 浏览无底线的数据时,点击某个链接跳转到新的页面,再回到上一页时希望停留在离开时的位置。
//模拟离开此页面弹窗提醒
beforeRouteLeave(to:any,from:any,next:any){
next(false);
setTimeout(()=>{
this.$confirm('是否继续?','提示',{
confirmButtonText:'确定',
cancelButtonText:'取消',
type:'warning'
}).then(()=>{
this.$router.go(-1);
next(false);
}).catch(()=>{
next();
});
},100);
}
历史模式
一般vue项目新建的时候都是默认采用history模式,但实际上历史模式分为两种,一种是history模式,一种是hash模型。最明显的区别就是hash模式会在地址栏中有#号,而history模式没有;同时由于history模式的实现原理用到H5的新特性,所以它对浏览器的兼容性有要求(IE >= 10)。
history模式
使用该模式,可能会存在一个问题,比如通过商品id跳转到了该商品的详情页,如果这个时候直接进行页面刷新会导致页面报错(出现404)。导致这个问题的原因是因为history模式的实现依赖 HTML5 History API 和服务器配置,举个简单的例子:
当前页面的url地址是IP地址:8080/home,在页面不刷新的情况下默认访问的始终是home这个路径下的index.html,但是一旦手动刷新页面后,访问的就是:ip地址:8080/home/index.html,很明显服务器没有这个资源,所以会出现404错误。这个时候就需要在后端进行一些配置:如果 URL 匹配不到任何静态资源,则应该返回同一个index.html页面。
// nginx
location / {
try_files $uri $uri/ /index.html;
}
hash模式
hash模式下url变化是通过浏览器的hashchange方法监听的,路由地址就是#后面的内容,切换路由变化的是#后面的内容,所以总是能请求成功得到index.html页面,再通过路由渲染显示对应得组件。而且相比较history模式,对浏览器的兼容程度也更高。