安装router
npm init vite@latest
npm install
npm install vue-router@4 -S
创建: src/router/index.ts
import {createRouter, createWebHistory} from 'vue-router'
const routes:Array<RouteRecordRaw> = [
{
path:'/',
name:'Login'
component:()=>import('../components/Login.vue')
},
{
path:'/reg',
name:'Reg',
component:()=>import('../components/Reg.vue')
},
{
path:'/logout/:id',
name:'Logout',
component:()=>import('../components/Logout.vue')
}
]
const router = createRouter({
history:createWebHistory(),
routes:routes
})
export default router
在main.ts中注册
import router from './router'
app.use(router)
在App.vue中使用
<router-link to="/">Login</router-link>
<router-link to="/reg">Regist</router-link>
<router-view></router-view>
路由的模式
createWebHashHistory()
location.hash = '/' 跳转到Login.vue 使用hash时url路径带有#
window.addEvenetListener('hashchange',(e)=>{ //监听浏览器前进后退按钮的变化
console.log(e)
})
createWebHistory() 基于H5的history来实现,URL不带#
window.addEvenetListener('popstate',(e)=>{ //监听浏览器前进后退按钮的变化
console.log(e)
})
history.pushState({state:1},'', '/reg') 不会被浏览器监听到
命名路由和编程式导航
<router-link to="{name:'Login'}">Login</router-link>
<router-link to="{name:'Reg'}">Regist</router-link>
或
<a href='/'>Login</a>
<a href='/reg'>Regist</a> //这种方式和router-link的不一样是页面会刷新
<router-view></router-view>
编程式导航
@click='toPage("/reg")'
import {useRouter} from 'vue-router'
const router = useRouter()
const toPage = (url:string)=>{
router.push(url)
或对象的形式
router.push({
path:url //还可以传递参数
})
也可以是命名式跳转,path改成name @click='toPage("Reg")'
router.push({
name:urlName //还可以传递参数
})
}
历史记录 使用replace来防止页面前进后退
<router-link replace :to="{name:'Login'}">Login</router-link>
编程式防止页面前进后退
router.replace({
path:url //还可以传递参数
})
编程式实现前进后退
const next = ()=>{
router.go(1);
//router.go(-1); 后退
}
const prev = ()=>{
router.go(-1); 或 router.back();
}
路由传参
A.vue
@click=toDetails(item)
import {useRouter} from 'vue-router'
import {data} from './data.js' //js中为{data:[{name:'Jason', price:2.0, id:1001},{}]}
type ItemData = {
name:string,
price:number,
id:number
}
const router = useRouter()
const toDetails = (item:ItemData)=>{
//query方式,参数拼接在url上,接收方也用query来取
router.push({
path:'/reg',
query:item
})
//params式传参,只能用name,参数不显示在url中
router.push({
name:'Reg',
params:item
})
//动态路由参数
router.push({
name:'Reg',
params:{
id:item.id
}
//或者直接params:item,因为item中有id属性
})
}
Reg.vue
//接收query式传参
{{ route.query.name }}
//接收params式传参
{{ route.params.name }}
import {useRoute} from 'vue-router'
const route = useRoute()
嵌套路由
适用于一个页面中部分内容不变,部分需要变化的场景,比如后台管理界面和手机界面
const routes:Array<RouteRecordRaw> = [
{
path:'/user',
component:()=>import('../components/Footer.vue')
children:[
{
path:'', //默认路由地址
name:'Login',
component:()=>import('../components/Login.vue')
},
{
path:'/reg',
name:'Reg',
component:()=>import('../components/Reg.vue')
}
]
}
]
Footer.vue
<router-view></router-view>
<router-link to="/user">Login</router-link>
<router-link to="/user/reg">Regist</router-link>
命名视图
const routes:Array<RouteRecordRaw> = [
{
path:'/',
component:()=>import('../components/Root.vue')
children:[
{
path:'/user1',
components:[
default:()=>import('../components/AAA.vue')
]
},
{
path:'/user2',
components:[
bbb:()=>import('../components/BBB.vue'),
ccc:()=>import('../components/CCC.vue')
]
}
]
}
]
Root.vue
<router-link to='/user1'>User1</router-link>
<router-link to='/user2'>User2</router-link>
<router-view></router-view>
<router-view name='bbb'></router-view>
<router-view name='ccc'></router-view>
重定向和别名
const routes:Array<RouteRecordRaw> = [
{
path:'/',
component:()=>import('../components/Root.vue'),
redirect: '/user1', //重定向 或{path:'/user1', query:{}} 或 {name:'User1',params:
{}} 或 to=>{return '/user1'} 或to=>{return {name:'User1',params:{}}}
alias:['/root','/rt'] //取别名
children:[
{
path:'/user1',
name:'User1',
components:[
default:()=>import('../components/AAA.vue')
]
},
{
path:'/user2',
components:[
bbb:()=>import('../components/BBB.vue'),
ccc:()=>import('../components/CCC.vue')
]
}
]
}
]
前置及后置守卫
import {createRouter, createWebHistory} from 'vue-router'
const routes:Array<RouteRecordRaw> = [
{
path:'/',
component:()=>import('@/views/Login.vue')
},
{
path:'/index',
component:()=>import('@/views/Index.vue')
}
]
const router = createRouter({
history:createWebHistory(),
routes:routes
})
export default router
登录成功后保存token
localStorage.setItem('token', '123');
前置守卫 main.ts中:
const whiteList = ['/']
router.beforeEach((to, from, next)=>{
if(whiteList.includes(to.path) || localStorage.getItem('token')) {
next()
}else{
next('/') //不在白名单或没有凭证的话,跳转回登录界面
}
})
后置守卫
LoadingBar.vue
defineExpose({
startLoading,
endLoading
})
main.ts中:
import { createApp, createVNode,render } from 'vue'
import loadingBar from '@/views/LoadingBar.vue'
const VNode = createVNode(loadingBar) //转换成虚拟dom
render(VNode, document.body) //将虚拟函数挂载到body
router.beforeEach((to, from, next)=>{
VNode.component?.exposed?.startLoading()
})
router.afterEach((to, from) => {
VNode.component?.exposed?.endLoading()
})
路由元信息
src/router/index.ts
declare module 'vue-router' {
interface RouteMeta {
title:string
}
}
const routes:Array<RouteRecordRaw> = [
{
path:'/',
component:()=>import('@/views/Login.vue'),
meta:{
title:'登录'
}
}
]
main.ts中:
router.beforeEach((to, from, next)=>{
document.title=to.meta.title
})
路由过渡动效
src/router/index.ts
declare module 'vue-router' {
interface RouteMeta {
title:string,
transition:string
}
}
const routes:Array<RouteRecordRaw> = [
{
path:'/',
component:()=>import('@/views/Login.vue'),
meta:{
title:'登录',
transition:'animate_fadein'
}
}
]
App.vue
<router-view #default='{route, Component}'>
<transition :enter-active-class="`animate__animated ${route.meta.transition}`">
<component :is='Component'></component>
</transition>
</router-view>
动态路由
1: 从后台返回路由配置信息
2: 登录成功后调用后台服务获取用户路由信息,使用addRoute和removeRoute来动态添加上删除路由信息
import {useRouter} from 'vue-router'
const router = useRouter()
const initRouter = async()=>{
const result = await axios.get('http://localhost:8080/login',{params:formInline})
result.data.route.forEach((v:any)=>{
router.addRoute({
path:v.path,
name:v.name,
component:()=>import(`../views/${v.component}`) //注意这里不能用@代替src
})
})
}