本节介绍了Vue3的Vue-Router的基础内容,包括安装、创建、动态路由、获取参数、路由切换、历史模式、导航守卫,并与Vue2.x的区别做出代码展示
文章目录
1、Vue-Router的安装及作用
通过路由系统将 组件 与可访问的url绑定在一起,
路由设计的目的:切换页面时让url路径变化,不触发HTML物理文件的加载,因此VueRouter的跳页模式不能使用普通的超链接方式
npm install vue-router --save //Vue2.x的安装方式,--save保存到依赖
npm install vue-router@next --save 或 npm install vue-router@4 // Vue3.x的安装方式
2、Vue-Router 创建
1) Vue3.x是使用 createRouter() 方法来创建的,
/*在main.js中*/
import router from './router/index.js'
app.use(router)
/*在index.js中*/
import {createRouter, createWebHistory,createWebHashHistory} from 'vue-router'
const router = createRouter({
history: createWebHistory(), //hash模式:createWebHashHistory,history模式:createWebHistory
routes: []
})
export default router
2) Vue2.x是通过 new Router() 方法来创建路由的,
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
routes: []
});
export default router;
3、动态路由
//Vue3.x写法
//添加路由
router.addRouter({path:'/one',name:'one',component:()=> import('...page1.vue')})
//添加子路由
router.addRouter('one',{path:'/son1',name:'son1',component:()=> import('...son1.vue')})
//Vue2.x写法
let routeA=[{ path: '/pageA', name: 'pageA', component:()=> import('...pageA.vue')}]
router.addRoutes(routeA);
4、路由匹配及404页面
const routes = [
{ path:'/article/:id(\\d+)',//正则匹配,仅匹配数字
component:article },
{ path:'/films/:id?', //正则匹配,'+'至少需要一个;'*'0或多个;'?'有或者没有,不可重复
component:films },
{ path:"/:path(.*)", //404页面路由
component:NotFound },
]
5、获取路由参数
//Vue3.x
import { useRoute,useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
const id = route.query.id
const title = route.meta.title //获取路由名称,可用于面包屑
//const path = router.push()
//Vue2.x
this.$route.query.id
注:$route:获取路由信息对象,只读; $router:操作路由对象 ,只写。
6、切换路由
1)使用router-link
<router-link to="/">首页</router-link> //Vue3.x与Vue2.x写法一致
2)编程式导航 router.push()、router.replace()、router.go()、router.resolve()
- router.push({}) 可回退
- router.replace(‘/’) 替换页面不能回退
- router.resolve()返回路由地址的标准化模板
使用:
let router = this.$router.resolve({
path: '/home',
query:{id:item.id}
})
window.open(router.href,'_blank') //路由跳转重新打开一个页面
//Vue3.x写法
import { useRouter } from 'vue-router'
setup(){
const router = useRouter()
router.push('/');
//携带参数跳转
router.push({path:'/news/123'})
router.push({name:'news',params:{id:3435}})
router.push({path:"/",query:{search:'特朗普'}}
router.replace('/') //替换页面,不能回退
router.go(1) //前进一页
router.go(-1) //后退一页
}
//Vue2.x写法
this.$router.push({path: '/bbb', query: {username: "abc"}});//$router.push()、$router.replace()、$router.go()
3)route与router的区别
$router:路由操作对象
$route:路由信息对象,路由参数的接收
this.$router.push("/user/list");
this.$router.push({name:'role'})
this.$router.push({name:'role-operate',params: {id: row.roleId }})
this.$router.push({name:'role-operate',params:{id:0}})
//在vue3中
//模板使用
$route.path 、$route.name
//在script中使用
import { useRoute,useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
const path = route.path
const title = route.meta.title
7、命名式路由
//写在App.vue
<router-view name="shopTop"></router-view>
<router-view></router-view>
<router-view name="shopFooter"></router-view>
//写在router的index.js
{ path:'/shop',
components:{
default:shopMain,
shopTop:shopTop,
shopFooter:shopFooter}
}
8、重定向与别名
{ //重定向
path:'/mail',
redirect:'/shop',
// redirect:to=>{return {path:'/shop'}} //函数式
}
{ //取别名
path:'/shop',
// alias:"/wlshop", //一个别名
alias:["/wlshop","/wl22shop"], //多个别名用数组表示
components:{shopMain }
},
9、hash 与 history 模式 、js代码实现原理
VueRouter为了支持单页面应用的页面管理和页面跳转,提供hash与history两种模式
// Vue2.x的两种模式
mode: 'history'
mode: 'hash'
// Vue3.x的两种模式
history: createWebHistory()
history:createWebHashHistory()
注:Vue3.x的模式是一个方法,而不是一个变量,不然会报这样的错误: Cannot use ‘in’ operator to search for ‘path’ in undefined。
两者模式的区别
①hash模式
使用锚点技术重写URL访问路径,在原有URL路径后拼接/#/xxx,不重新加载原有HTML文件的基础上,实现切换URL路径的目的,实现原理:使用onhashchange
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.page{ width:400px;height:400px}
.index{background-color: #42b983;display: none;}
.about{background-color: #f37873;display: none;}
.third{ background-color: #EEE111;display: none;}
</style>
</head>
<body>
<a href="#/index" >访问首页</a>
<a href="#/about">关于页面</a>
<div class="page index">我是首页</div>
<div class="page about">关于页面</div>
<div class="page third">第三个页面</div>
<script type="text/javascript">
window.onhashchange = function (event) { //url的hash部分切换事件
var newURL = event.newURL.split('#/')[1] //获取要跳转的url路径并截取页面名称
var oldURL = event.oldURL.split('#/')[1] //获取跳转时的起点页面路径并截取页面名称
var newPage = document.querySelector('.'+newURL) //获取两个页面的dom名称
var oldPage = document.querySelector('.'+oldURL)
newPage.style.display = 'block' //显示目标页面
oldPage.style.display = 'none' //隐藏当前页面
}
</script>
</body>
</html>
hsah模式利用纯静态技术,不触发网页重新加载情况下切换url路径,配合onhashchange()实现,hssh部分发生变化,触发函数,通过JS编程实现DOM对象切换展示。
不足:
- 在分布式微前端中,嵌套的子应用与主应用都使用hash模式时,由于hash模式的url路径只能有一个#,导致子应用与主应用在定义url路径存在困难
- hash模式的url路径包含#,视觉上不美观
②history模式
不使用锚点技术重写URL路径,history的 url 不存在#,在视觉上更加美观
采用history对象中的pushState()函数重写URL路径,在触发重新加载的情况下变更URL路径,
需要服务器的重定向
原理是:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>history</title>
<style>
.page{ width:400px;height:400px}
.index{background-color: #42b983;display: none;}
.about{background-color: #f37873;display: none;}
.third{ background-color: #EEE111;display: none;}
</style>
</head>
<body>
<a href="javascript:jump('/index')" >首页</a>
<a href="javascript:jump('./about')">关于页面</a>
<a href="javascript:jump('./third')">第三个</a>
<div class="page index">我是首页</div>
<div class="page about">关于页面</div>
<div class="page third">第三个页面</div>
<script type="text/javascript">
function jump(path) {
history.pushState(null,'page',path) //重写URL路径为超链接传入的名称
var pages = document.querySelector('.page') //获取所有页面组件
var newPage = document.querySelector(path.replace('/','.')) //获取指定跳转的目标页面对象
pages.forEach(item=> item.style.display = 'none') //隐藏其他页面
newPage.style.display = 'block' //展示跳转的页面
}
</script>
</body>
</html>
history模式重写URL的解决方案是javascript:jump,导致的问题是新路径不包含原有HTML物理文件的访问地址,一旦刷新网页会造成404,VueCli在开发环境中解决了history模式刷新问题,但在生产环境下,还需要配合服务器转发重定向。
10、导航守卫
路由守卫就是路由跳转过程中的一些钩子函数,在路由跳转的时候,做一些判断或其他的操作。类似于组件生命周期钩子函数。
1) Vue3.x未改变部分
beforeEach前置守卫,beforeResolve 路由解析前,afterEach 路由跳转后执行
分类
//(1).全局路由守卫
beforeEach(to,form,next)全局前置守卫,路由跳转前触发。
beforeResolve(to,from,next)全局解析守卫在所有组件内守卫被解析后触发。
AfterEach(to,from)全局后置守卫,路由跳转完成后触发。
//(2).路由独享守卫
beforeEnter(to,from,next) 路由对象单个路由配置 ,单个路由进入前触发。
//(3).组件路由守卫
beforeRouteEnter(to,from,next)在组件生命周期 beforeCreate 阶段触发。
beforeRouteUpdate(to,from,next)当前路由改变时触发。
beforeRouteLeave(to,from,next)导航离开该组件的对应路由时触发。
//beforeEnter路由独享的守卫
{ path:'/page', //在路由配置上定义
component:page,
beforeEnter:(to,from)=>{console.log('beforeEnter')}
},
//beforeEach前置守卫,看用户有没有权限跳转到对应的页面
router.beforeEach((to, from,next) => {
console.log('to-from',to,from)
next()
// return false 返回 false 以取消导航
})
//beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave(生命周期钩子)
beforeRouteEnter((to, from, next)=>{})
项目使用的路由守卫
通过 beforeEach 设置登录后获取用户可进入跳转权限
当用户访问登录或者404页面可直接跳转
if(to.name==='login'||to.name === '404'){
next()
}
从 store 状态管理中获取用户登录后用户 token
引入store状态管理
import store from '@/store'
获取状态管理中用户 token
Const auth:any = store.state
Const isLogin = !!Auth.authstore.token
当存在 token 时,先判断用户是否存在路由权限后请求用户的路由权限。
if (isLogin) {
if (auth.authStore.routerPermission.length === 0) {
getRouterList().then(({ data }) => {
store.dispatch('authStore/setRouterPermission', data)
if (data.length === 0)
next({ name: 'Login', query: { redirect: to.fullPath } })
} else {
if (from.path === '/login' || to.path === '/') {
next({ name: data[0].name })
} else {
next()
}
}
})
}
}else{}
2) Vue3.x新增(组件内的守卫)
onBeforeRouteEnter,onBeforeRouteUpdate,onBeforeRouteLeave
onBeforeRouteLeave((to, from, next)=>{ //根据Vue3.x提供的生命周期钩子
const bool = window.confirm('你确定要离开当前页面吗?');
if(!bool) { return false }
})
11、监听路由变化
//Vue3.x写法
import { useRoute } from 'vue-router'
setup(){
const route = useRoute();
watch(route.query,(query)=>{ console.log(query); })
}
//Vue2.x写法
watch:{
'$route.path':function(newVal,oldVal){}
}