
vue3中vue-router详解
https://juejin.cn/post/7143890189524402183
安装
shell
npm install vue-router@4
新建router.js文件
src/router/router.js
js
const routes = [
{
path: '/',
redirect: '/login',
},
{
path: '/home',
name: 'home',
// 懒加载路由
component: () => import('@/pages/home/Index.vue'),
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/Index.vue'),
}
]
export default routes
src/router/router.config.js文件
js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './router'
const router = createRouter({
// 这里使用hash模式路由 createWebHistory=history 模式
history: createWebHashHistory(),
routes,
})
export default router
注册路由
main.js中注册路由
js
import { createApp } from 'vue'
// 引入路由
import router from './router/router.config.js'
const app = createApp(App)
app.use(router)
app.mount('#app');
挂载路由
app.vue中挂载路由
vue
<template>
<router-view />
</template>
嵌套路由
1、在所需嵌套路由下添加children数组,children中为嵌套路由
这里需要注意,子路由的路径path不能在前面添加 “/”,否则会被认定为一级路由
使用redirec属性用来设置嵌套默认路由,路径必须写完整
json
{
path: '/home',
name: 'home',
component: () => import('@/pages/home/Index.vue'),
children:[
{
path: "menu1",
name: "menu1",
component: () => import('@/pages/menu1/Index.vue')
},
{
path: "menu2",
name: "menu2",
component: () => import('@/pages/menu2/Index.vue'),
}
],
redirect: '/home/menu1',
},
获取当前路由路径
js
import { useRouter } from 'vue-router'
const router = useRouter();
const path = router.currentRoute.value.path;
console.log(path) //结果:http://localhost:3002/#/text/text2 => /text/text2
编程式路由跳转
1、template中跳转方式,直接$router.push()即可
vue
<button @click="$router.push('login')">跳转到登陆页</button>
<!--带参数的跳转-->
<button @click="$router.push({ path: 'login', query: { id: item.id } })">跳转到登陆页</button>
2、类似get请求,请求参数暴露在地址栏中
使用path定义路径,query传递参数
js
import { useRouter,useRoute } from 'vue-router'
// 跳转
const router = useRouter();
router.push({
path:'/home',
query:{ id:1 }
})
// 接收参数
const router = useRoute()
console.log('id:'+router.query.id)
3、类似post请求,请求参数不会暴露在地址栏中
使用name定义跳转路由名称,params传递参数
js
import { useRouter } from 'vue-router'
// 跳转
const router = useRouter();
router.push({
name:'home',
params:{ id:1 }
})
// 接收参数
const router = useRoute()
console.log('id:'+router.params.id)
404路由
很简单,只需要在路由上加一个配置就行,自动就跳转到404组件
js
import { createRouter, createWebHistory } from 'vue-router'
// 路由配置
const routes = [
{
path: '/',
name: 'Home',
component: import('@/components/Home.vue')
},
// ...其他路由规则
{
path: '/404',
component: () => import('@/components/NotFound404.vue')
},
{
path: '/:pathMatch(.*)*', // 捕获所有未匹配的路径
redirect: '/404'
}
]
// 创建路由实例
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
根据路径动态加载路由
js
import { createRouter, createWebHashHistory } from 'vue-router'
//路由列表,假设目前只有一个路由
let modules = reactive([
{
path: '/login',
component: createNameComponent(() => import('@/views/system/login.vue')),
meta: { title: '登录' }
}
])
//路由对象
const router = createRouter({
history: createWebHashHistory(),
routes: modules
})
// 1、在路由配置文件中预先加载所有组件
const viewModules = import.meta.glob('@/views/**/*.vue');
// 2、后端路径格式处理
// 确保后端返回的路径与 Vite Glob 的 key 格式匹配,例如:
// 后端返回路径 ➔ "/main/user/index"
// 需要转换为 ➔ "/src/views/main/user/index.vue"
const convertBackendPathToViteKey = (backendPath) => {
// 示例转换逻辑(根据实际项目结构调整)
return `/src/views${backendPath}.vue`;
};
// 3、动态路由加载实现
// 动态添加路由的方法
const addDynamicRoute = async (backendPath, routePath) => {
// 转换路径格式
const viteKey = convertBackendPathToViteKey(backendPath);
// 获取预加载的模块
const moduleLoader = viewModules[viteKey];
if (!moduleLoader) {
console.error(`Component not found: ${viteKey}`);
return;
}
// 加载组件
const module = await moduleLoader();
const component = module.default;
//路由配置
const item = {
path: routePath,
component: component
}
//特别注意,除了加入router 还需要添加到modules里面
modules.push(item)
// 添加路由
router.addRoute(item);
};
// 使用示例(假设后端返回路径为 "/main/user/index")
addDynamicRoute('/main/user/index', '/user');
路由守卫
路由守卫分为全局路由守卫,路由独享守卫,组件路由守卫
全局路由守卫
beforeEach(to, from, next):全局前置守卫,路由跳转前触发
- to:即将要进入的目标路由对象
- from:即将要离开的路由对象
- next: next 是一个方法,代表的是是否展示路由页面,如果不使用next方法,那么指定页面无法显示
使用:在进行登录权限时候进行使用,如果没有token,则回到登录页
js
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 全局守卫:登录拦截 本地没有存token,请重新登录
router.beforeEach((to, from, next) => {
// 判断有没有登录
if (!localStorage.getItem('token')) {
if (to.name == "login") {
next();
} else {
router.push('login')
}
} else {
next();
}
});
afterEach(to, from):全局后置守卫,路由跳转后触发
beforeResolve(to, from, next): 全局解析守卫 在所有组件内守卫和异步路由组件被解析之后触发
路由独享守卫
之前的全局守卫,是定义的全局路由守卫,现在的是路由独享的守卫,在配置路由时,写在路由参数内部
- beforeEnter(to,from,next) 路由对象单个路由配置 ,单个路由进入前触发
json
{
path: '/admin',
name: 'admin',
component: () => import('../views/mine/admin.vue'),
//判断是否登陆代码,点击进入admin也面时,路由独享守卫启用
beforeEnter:(to,form,next)=>{
if (!localStorage.getItem('user')) {
if (to.name == "login") {
next();
} else {
router.push('login')
}
} else {
next();
}
}
}
组件路由守卫
beforeRouteEnter(to,from,next)在组件生命周期beforeCreate阶段触发
js
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
}
beforeRouteUpdadte(to,from,next)当前路由改变时触发
js
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to,from,next)导航离开该组件的对应路由时触发
js
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
使用 watch 监听 $route 对象
vue
<template>
<div>
<!-- 组件内容 -->
</div>
</template>
<script setup>
import { useRoute, useRouter } from 'vue-router'
import { watch } from 'vue'
const route = useRoute()
watch(route, (toParams, previousParams) => {
// 响应路由变化
console.log('路由变化', toParams, previousParams)
}, { deep: true }) // 深度监听以捕获所有变化
</script>
使用 onBeforeRouteUpdate 钩子
vue
<template>
<div>
<!-- 组件内容 -->
</div>
</template>
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
onBeforeRouteUpdate((to, from) => {
// 在当前路由改变,但是该组件被复用时调用
console.log('路由更新', to, from)
})
</script>