Skip to content
鼓励作者:欢迎打赏犒劳

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>

如有转载或 CV 的请标注本站原文地址