vue3中vue-router详解:基本使用,路由跳转,嵌套路由,动态路由,路由守卫

11,817 阅读4分钟

1、基本使用

1、安装路由依赖模块

npm install vue-router@4

2、在src文件夹下新建router文件夹,在router文件夹下新建router.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

3、在src文件夹下新建router.config.js文件

import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './router'

const router = createRouter({
// 这里使用hash模式路由
  history: createWebHashHistory(),  
  routes,
})

export default router

4、main.js中注册路由

import { createApp } from 'vue'
// 引入路由
import router from './router.config'

const app = createApp(App)
app.use(router)

5、app.vue中挂载路由

<template>
  <router-view />
</template>

登陆页效果

image.png

2、编程式路由跳转

vue3中路由跳转和vue2中类似,也是使用router.push方法

1、template中跳转方式,直接$router.push()即可

<button @click="$router.push('login')">跳转到登陆页</button>

2、类似get请求,请求参数暴露在地址栏中

使用path定义路径,query传递参数

import { useRouter } 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传递参数

import { useRouter } from 'vue-router'

// 跳转
const router = useRouter();
router.push({ 
    name:'home', 
    params:{ id:1 } 
}) 

// 接收参数
const router = useRoute()
console.log('id:'+router.params.id)

3、嵌套路由

1、在所需嵌套路由下添加children数组,children中为嵌套路由

这里需要注意,子路由的路径path不能在前面添加 “/”,否则会被认定为一级路由

使用redirec属性用来设置嵌套默认路由,路径必须写完整

 {
    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',
  },

2、在home.vue组件中使用嵌套路由,为了页面美观,这里使用了element-plus中的el-menu菜单组件,这里可以直接使用 router-link 完成二级路由切换,也可以使用编程式路由跳转。除此之外,别忘了在内容展示区域使用 router-view 注册

<template>
  <div class="home">
    <el-container>
      <el-header>
      </el-header>
      <el-container>
        <el-aside width="160px">
          <el-menu active-text-color="#ffd04b"
                   background-color="#545c64"
                   class="el-menu-vertical-demo"
                   default-active="菜单一"
                   text-color="#fff">
            <!-- 主要代码 -->
            <el-menu-item :index="item.name"
                          v-for="(item,index) in memuList"
                          :key="item.name"
                          @click="goRouter(item)">
              <span>{{item.name}}</span>
              <!-- 直接使用<router-link>完成二级路由切换 -->
              <!-- <router-link :to="item.path">{{item.name}}</router-link> -->
            </el-menu-item>
          </el-menu>
        </el-aside>
        <el-main>
          <!-- 在内容展示区域使用router-view注册 -->  
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script setup>
import { ref } from 'vue'

import { useRouter } from 'vue-router'
const router = useRouter()

// 菜单列表
let memuList = ref([
  { name: '菜单一', path: '/menu1' },
  { name: '菜单二', path: '/menu2' }
])

//  编程式路由跳转
const goRouter = (item) => {
  router.push(`/home${item.path}`)
}

</script>

嵌套子路由1

image.png

嵌套子路由2

image.png

4、动态路由

在做后台管理系统时,经常会遇到有些页面只有管理员能访问,普通用户是不能访问的,这时候就要对路由进行限制, 比如菜单三的管理页面只有管理员能够访问,其他人员不能访问 image.png 具体实现方法:

  1. 将只有管理员能访问的manage管理页面设为动态路由

新建dynamicRoute.js,存储动态路由,因为这里的manage作为二级子路由被添加的,所以这里的path不能加上'/'

//动态路由
const manage = {
  path: 'manage',
  name: 'manage',
  component: () => import('@/pages/manage/Index.vue'),
}

export default manage
  1. 用户登录后,通过接口获取到用户的登录身份,如果为管理员身份,使用router.addRoute()方法来添加动态路由

这里manageRoute是作为home的二级路由添加的,因此这里指定home就能将manageRoute添加为home的子路由

// 添加动态路由
import { useRouter } from 'vue-router'
import manageRoute from "@/router/dynamicRoute";

//这里调用接口获取用户身份就省略不写了
......
const router = useRouter()
// 这里manageRoute是作为home的二级路由添加的,因此这里指定home就能将manageRoute添加为home的子路由
router.addRoute("home", manageRoute)
  1. 页面刷新后,会造成动态路由消失,因此在app.vue页面监听router变化,重新添加路由
<script>
import manage from "@/router/dynamicRoute"
export default {
  watch: {
    $route: {
      async handler (newVal) {
        /* 在4.x版本中需手动调用router.replace方法重定向,
        因为动态路由页面刷新时,matched的值为空;
        在3.x版本中,刷新页面添加异步路由,matched有值,不需要再重定向 */
        this.$router.addRoute("home", manage)
        /* 在动态路由页面刷新时,matched数组为空 */
        if (!newVal.matched.length && newVal.fullPath === "/home/manage") {
          await this.$router.replace("/home/manage")
        }
      },
    },
  },
};
</script>

4、路由守卫

路由守卫分为全局路由守卫,路由独享守卫,组件路由守卫

(1)全局路由守卫

  1. beforeEach(to, from, next):全局前置守卫,路由跳转前触发

to:即将要进入的目标路由对象

from:即将要离开的路由对象

next: next 是一个方法,代表的是是否展示路由页面,如果不使用next方法,那么指定页面无法显示

使用:在进行登录权限时候进行使用,如果没有token,则回到登录页

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();
	}
});
  1. afterEach(to, from):全局后置守卫,路由跳转后触发
  2. beforeResolve(to, from, next): 全局解析守卫 在所有组件内守卫和异步路由组件被解析之后触发

(2)路由独享守卫

之前的全局守卫,是定义的全局路由守卫,现在的是路由独享的守卫,在配置路由时,写在路由参数内部

  1. beforeEnter(to,from,next) 路由对象单个路由配置 ,单个路由进入前触发
{
	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();
		}
	}
}

(3)组件路由守卫

  1. beforeRouteEnter(to,from,next)在组件生命周期beforeCreate阶段触发
 beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
 }
  1. beforeRouteUpdadte(to,from,next)当前路由改变时触发
 beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  1. beforeRouteLeave(to,from,next)导航离开该组件的对应路由时触发
  beforeRouteLeave (to, from, next) {
      // 导航离开该组件的对应路由时调用
      // 可以访问组件实例 `this`
  }