vue3静态路由及动态路由的简单配置

2,621 阅读3分钟

vue3静态路由及动态路由的简单配置

  • 静态路由配置,是指路由routes放在前端js文件中;
  • 动态路由配置,是指路由routes从后端接口获取,动态加载。

app.vue文件的内容

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
</script>

<template>
  <router-view v-slot="{ Component }">
    <transition name="el-fade-in" mode="out-in">
      <component :is="Component" />
    </transition>
  </router-view>
</template>

<style scoped>

</style>
  • 创建src/router/index.js文件
  • main.js文件引用src/router/index.js
import router from './router/index'

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

一、静态路由配置

src/router/index.js文件内容(对应的vue文件及文件夹要先创建)

import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [{
  path: "/",
  redirect: "/Index",
  meta: { title: '首页' }
}, {
  path: "/Index",
  name: "Index",
  component: () => import('@/views/Index/index.vue'),
  meta: { title: '首页' },
  children: []
}, {
  path: "/Login",
  name: "Login",
  component: () => import('@/views/Login/index.vue'),
  meta: { title: '登录' },
  children: []
}, {
  path: "/NotFound",
  name: "NotFound",
  component: () => import('@/views/NotFound/index.vue'),
  meta: { title: '404' },
  children: []
}, {
  path: "/Personal",
  name: "Personal",
  component: () => import('@/views/Personal/index.vue'),
  meta: { title: '个人中心' },
  children: []
}]

const router = createRouter({
    history: createWebHashHistory(),
    routes: routes,
    scrollBehavior() {
        return {
            top: 0
        }
    }
})
router.beforeEach((to, from, next) => {
    // 进入页面前处理(如:进度条,页面条件判断等)
    // console.log(to.name);
    next()
})
router.afterEach((to, from) => {
    // 进入页面后处理(如:进度条结束)
    try {
        //   console.log(to.name);
    } catch (err) {
        console.log(err, to, from);
    }
})
export default router

二、动态路由配置

src/router/index.js文件内容(对应的vue文件及文件夹要先创建)

import { createRouter, createWebHashHistory } from 'vue-router'
import { userStore } from '../store/index.js' 
// 此处使用的是pinia储存,(vuex相似,pinia相对使用更方便)
// pinia的具体使用方法此处不做说明

const routes = [{
  path: "/",
  redirect: "/Index",
  meta: { title: '首页' }
}, {
  path: "/Index",
  name: "Index",
  component: () => import('@/views/Index/index.vue'),
  meta: { title: '首页' },
  children: []
}, {
  path: "/Login",
  name: "Login",
  component: () => import('@/views/Login/index.vue'),
  meta: { title: '登录' },
  children: []
}, {
  path: "/NotFound",
  name: "NotFound",
  component: () => import('@/views/NotFound/index.vue'),
  meta: { title: '404' },
  children: []
}]
// 注意:此处routes和静态routes不同之处,动态的路由的routes部分必须有的路由,在这些路由中页面加载其他路由。


const router = createRouter({
  history: createWebHashHistory(),
  routes,
  scrollBehavior() {
    return {
      top: 0
    }
  }
})

// 路由拦截
router.beforeEach((to, from, next) => {
  const store = userStore()  
  // 获取pinia中储存的路由数据(1、固定值 2、从登录接口中获取储存的)
  // 若是使用vuex,取值方法类似
  
  const list = router.getRoutes() 
  // 获取当前路由中routes信息,和routes长度对比,若是长度相等,则需要加载动态的路由
  if (list.length == routes.length) {
    store.menuList.forEach((v) => {
      const val = {
        ...v,
        name: v.perms,
        meta: { title: v.menuName },
        component: eval(`() => import("${v.component}")`)
      }
      // perms、menuName、component是和后端约定的菜单信息字段,可能是其他值,根据具体情况觉得
      // component字段内容是‘/src/views/Personal/index.vue’。
      // 建议:perms、menuName字段直接使用name、title更方便。
      // 注意:component的引用方法eval()和routes中的引用区别
      router.addRoute(val)
    })
  }

  if (!!store.userInfo?.access_token) {
    // 根据是否有token(即store.userInfo.access_token)
    // 有登录信息
    if (to.matched.length > 0) {
      // 页面路径存在
      next()
    } else {
      // 页面路径不存在(判断是否是刷新的页面)
      const obj = router.getRoutes().find(v => v.path == to.path)
      // 此处判断可以用from中path判断,也可以判断obj是否存在
      if (!!obj) next(obj.path)
      else next('/NotFound')
      // 注意:此处判断必须做
      // 不做不影响第一次加载,若是刷新页面,则所有动态页面都会跳转404页面
    }
  } else {
    // 无token登录信息,去登录页
    if (to.path == '/Login') {
      // 当前页面为登录页
      next()
    } else {
      // 当前页面为非登录页
      next('/Login')
    }
  }
})

router.afterEach((to, from) => {
    try {
        //   console.log(to.name);
    } catch (err) {
        console.log(err, to, from);
    }
})
export default router

注:

此文仅适合简单动态路由,如果是复杂的动态路由,如:进度条、路由权限、菜单栏为公共组件等相对复杂的动态路由可以在此基础上添加功能。