Vue3路由详情(vue-router)
- 一、路由vue-router说明
- 二、路由使用
- [三、< route-link >属性及其它介绍](#三、< route-link >属性及其它介绍)
- [四、Not Found](#四、Not Found)
- 五、路由嵌套/子路由
- 六、路由传参
- 七、路由导航守卫(7个钩子函数)
-
- 1、基础介绍
- 2、7个导航守卫函数介绍
-
- [2-1 全局守卫](#2-1 全局守卫)
- [2-2 组件守卫(在组件中定义)](#2-2 组件守卫(在组件中定义))
- [2-3 独享守卫](#2-3 独享守卫)
- 3、路由使用
- 八、动态添加删除路由
- 九、Vue3中引入router
一、路由vue-router说明
1.createWebHashHistory(process.env.BASE.URL):hash路由
2.createWebHistory:history路由
3.createMemoryHistory:带缓存history路由
4.parseQuery:查询参数反序列化
5.stringfiyQuery:查询参数序列化
6.onBeforeRouteLeave:路由离开钩子
二、路由使用
1.切换触发:
< router-link to="/home">Home</ router-link >
2.显示< router-view >< /router-view >
三、< route-link >属性及其它介绍
- to:字符串/对象;
- replace:设置成replace属性的话,当点击时,会调用router.replace(),而不是router.push();
- active-class:设置激活a元素后应用的class,默认是route-link-active;
- exact-active-class:链接精准激活时,应用于渲染的< a >的class,默认是route-link-exact-active;
四、Not Found
Not Found:没有匹配到路由会展示的页面;
比如NotFound的错误页面中,可以编写一个动态路由用于匹配所有的页面:
typescript
{
path:'/:pathMatch(.*)',
component:()=>import ('@/view/NotFound.vue');
}
可以通过$route.params.pathMatch获取传入的参数,匹配规则加 * : path:'/:pathMatch(.*)'。
五、路由嵌套/子路由
typescript
{
path:'/home',
component:Home,
children:[
{path:'',redirect:'/home/product'},
{path:'producedetail',redirect:'/home/producedetail'},
]
}
六、路由传参
1、方式一:query
typescript
router.push({
path:'/about',
query:{name:'张三'}
})
// 通过$route.query获取参数
// query传参:参数会显示在地址,F5刷新不会清空
2、方式二:params
typescript
router.push({
name:'About',
params:{name:'张三',age:18}
})
// 通过$route.params获取参数
// params传参:参数不会显示在地址,F5刷新会清空
// 注意:src/routes/index.ts
[
{
path:'/about',
name:'About',// 一定要写,params通过name识别路径
component:About
}
]
3、方式三:标签传参
typescript
// 标签传参
< router-link :to="{path:'/login',query:{name:'张三'}}">Home</ router-link >
< router-link :to="{name:'About',params:{name:'李四'}}">About</ router-link >
// 接受参数
this.$route.query
this.$route.params
4、方式四:路由配置
typescript
{
path:'/about/:id',
name:'About',
component:About
}
// 通过$route.params获取参数
//或
this.$router.push({
path:'/about/:id',
})
七、路由导航守卫(7个钩子函数)
1、基础介绍
一共7个钩子函数,除了afterEach没有next参数,只有to,from,其他的钩子函数都有to,from,next3个参数。
to :即将进入的目标路由;
from:即将离开的路由;
next:是一个函数,一定要调用这个函数来resolve钩子函数。否则不能正常切换路由。
注意:参数或查询的改变并不会触发进入/离开组件的导航守卫(beforeRouteEnter、beforeRouteLeave)
2、7个导航守卫函数介绍
2-1 全局守卫
beforeEach:全局前置守卫
①地址栏发生变化就会触发,不管组件是否复用;
②创建多个beforEach时会按照顺序触发,不会覆盖;
③必须执行next函数;
④它在beforeResolve执行前执行;
beforeResolve:全局解析守卫
①同上①
②在beforeEach执行之后执行,在所有的组件守卫执行完成后执行;
afterEach:全局后置钩子(不含next)
①同上①
④它在beforeEach、beforeResolve执行后执行;
2-2 组件守卫(在组件中定义)
beforeRouteEnter
①该函数在进入该组件时执行,一般是通过导航变化然后进入组件时执行,如果只是组件复用是不执行该函数的;
②该函数中没有this,因为该函数执行时组件实例还没有创建,不可以通过调用next函数中回调函数,回调函数的第一个参数就是该组件的实例,不过回调函数是异步时,他需要等到组件实例创建完后再调用该回调函数执行;
③该函数执行晚于beforeEnter;
beforeRouteUpdate
①该函数只在组件发生复用时才执行,在第一次进入组件时不执行;
②该函数在beforeEach之后,在beforeResolve之前执行;
beforeRouteLeave
①该函数只有在离开该组件时执行,在组件复用时不执行;
②在通过导航进行组件间的切换时,一般先要执行即将离开的组件的beforeRouteLeave函数然后再执行全局beforeEach守卫;
2-3 独享守卫
beforeEnter
①只有进入对应路由时才会执行,组件复用说明是同一个路由间的导航切换,不会触发;
②函数在beforeEach之后执行,在beforeRrouteEnter之前执行。
typescript
[
{
path:'/about',
name:'About',
component:About,
beforeEnter(to,from,next){
if(to.path=='test'){
next();
}else{
next();
}
}
}
]
3、路由使用
typescript
//src/router/index.ts(全局守卫)
//...
export const router = createRouter({
//...
});
router.beforeEach((to,from,next)=>{
next();
})
...beforeResolve...
...afterEach...
typescript
// src/views/About.vue(组件守卫)
<script lang="ts">
import { definecomponent } from 'vue';
export default definecomponent({
name:'About',
methods:{},
beforeRouteEnter(to,from,next){
next();
}
...beforeRouteUpdate...
...beforeRouteLeave...
})
</script>
八、动态添加删除路由
1、vue-router动态路由及菜单实现
- router.addRoutes(routes:Arrauy< RouteConfig >)
动态添加的路由规则。参数必须是一个符合routes选项要求的数组。
typescript
// routes选项
{
path:'',
name:'',
component:'',
meta:{title:"",icon:"",role:[]},
children:[]
}
2./src/router/index.ts改造
- 加载静态路由,用户能直接访问的路由,不需要判断权限就能直接展示的;
- 加载动态路由,需要判断用户权限,需要从后台传过来,需要动态动态生成菜单的。
== 静态路由 ==:创建src/router/default.js;一般是首页,登录页,404,没有权限;
== 动态路由 ==:什么时候注册?在哪里注册?怎么注册?登录之后注册;在路由守卫里面注册,用router.addRoute()一个个加进去。
typescript
// src/router/index.ts
...
import routeAssembler from './setup';
import { hasAuthority } from '@/utils/login.js';
...
//路由守卫
let registerRouteFresh = true;// 是否动态加载过
router.beforeEach((to,from,next) => {
const isLogin = localStorage.isLogin ? true : false;
if ( isLogin ){
// 已登录
let isAccess = hasAuthority ( to.meta.access );
if ( !isAccess ){// 没有权限
next('/notAccess');
return;
}
if ( registerRouteFresh ){//还没有动态加载过
// 动态注册路由
routeAssembler ( router );
registerRouteFresh = false;
next({...to,replace:true})
}else{
// 已经登录了,不能再打开登录页
to.path === '/login'? next('/home'):next();
}
} else {
// 如果无须登录则直接打开,否则转向登录页面
to.meta.nologin || to.path === '/login'? next():next('/login');
}
})
...
如何动态注册?
typescript
@/router/setup.js
// 即上段代码中的routeAssember:
import fixItems from "./default"; // 默认路由
import {HomeName} from './default';// 统一命名首页路由页
import projectItems from '@/modules/router'; //具体业务系统的路由
export default (router)=>{
//获取动态路由
const dynaItems = getDynamicItems();
//对齐首页(统一命名首页)
adPatHome(HomeName,dynaItems);
//添加动态路由
dynaItems.forEach(value=>{
router.addRoute(value);
})
//获取动态路由(后台)
const getDynamicItems=()=>{
//...从后端获取...
return projdctItems
}
//默认路由与业务路由对齐首页的路由信息
//所谓对齐,就是所有name保持一致,这样才能保证动态加入的路由项,覆盖掉前面path和name相同的路由。
const adPatHome=(HomeName,dynaItems)=>{
let home = dynaItems.filter(item=>{
return item.path === '/';
})
if(home.length >0 && home[0].name!==HomeName){
home[0].name=HomeName;
}
}
}
2、动态删除路由
== 方式一 == 添加一个name相同的路由;
typescript
router.addRoute({path:'about',name:'about',component:'About'})
== 方式二 ==通过removeRoute方法传入路由名称;
typescript
router.removeRoute('about')
九、Vue3中引入router
typescript
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = userRouter();
// 相当于vue2中的this.$route,this.$router