前端开发之vue动态路由实现方案

前言

本篇讲解的路由实现方案:默认存在的路由json->登录获取路由的json数据和权限->index.vue页面通过watch监听router为路由附加默认值->通过router.push跳转->触发beforeEach实现页面权限的判断和addrouter合并路由列表

2. 实现

1、登录页面创建登录函数和watch监听路由

//redirect 赋值
watch: {
    
    
    $route: {
    
    
      handler (route) {
    
    
        this.redirect = (route.query && route.query.redirect) || '/'
      },
      immediate: true
    }
  },
//登录函数
const ruleForm = ref('')
const login = (userInfo) => {
    
    
    dispatch('user/login', userInfo)
}
const handleRoute = () => {
    
    
  return data.redirect === '/404' || data.redirect === '/403'
  ? '/'
  : data.redirect
}
const handleLogin = () => {
    
    
  ruleForm.value.validate(async (valid) => {
    
    
  if (valid) {
    
    
    try {
    
    
      data.loading = true
      await login(data.forms)
      await router.push(handleRoute())
      } finally {
    
    
         data.loading = false
      }
    }
  })
}

2、调用的login方法

(1)登录方法

const actions = {
    
    
	//登录成功将token存储到localStorage中,并为vuex的token中赋值
  async login ({
     
      commit }: {
     
      commit: any }, userInfo: any) {
    
    
    // const { data } = await login(userInfo)
    // const token = data[tokenName]
    const token = 'admin-token-bbfd1c4e-4e11-F71E-B4B6-aEbCE62cDC3A'
    if (token) {
    
    
      commit('setToken', token)
      const hour = new Date().getHours()
    } else {
    
    
      const err = `登录接口异常,未正确返回${
      
      tokenName}...`
      throw err
    }
  }
}

(2)存储token

 * @description 存储token
 * @param token
 */
export function setToken (token:any) {
    
    
  if (storage) {
    
    
    if (storage === 'localStorage') {
    
    
      return localStorage.setItem(tokenTableName, token)
    } else if (storage === 'sessionStorage') {
    
    
      return sessionStorage.setItem(tokenTableName, token)
    } else if (storage === 'cookie') {
    
    
      return cookie.set(tokenTableName, token)
    } else {
    
    
      return localStorage.setItem(tokenTableName, token)
    }
  } else {
    
    
    return localStorage.setItem(tokenTableName, token)
  }
}

3、router.push的时候调用路由守卫

(1)创建路由守卫,建议路由守卫封装为单独的文件

详细讲解了路由的跳转和

/**
 * @description 路由守卫
 */
import store from '@/store'
import router from '@/router'
import getPageTitle from '@/utils/pageTitle'
import {
    
     toLoginRoute } from '@/utils/routes'
import configOb from '@/config'
//调用封装的配置文件
//intelligence(前端导出路由)和all(后端导出路由)两种方式
//authentication: 'intelligence',
const {
    
     authentication } = configOb
export function setup () {
    
    
  router.beforeEach(async (to, from, next) => {
    
    
    //获取token
    let hasToken = store.getters['user/token']
    if (hasToken) {
    
    
      if (store.getters['routes/routes'].length) {
    
    
        // 禁止已登录用户返回登录页
        if (to.path === '/login') {
    
    
          next({
    
     path: '/' })
        } else next()
      } else {
    
    
      	//setRoutes:下面讲解,存储vuex中routes,合并路由列表
        await store.dispatch('routes/setRoutes', authentication)
          next({
    
     ...to, replace: true })
      }
    } else {
    
    
      next(toLoginRoute(to.path))
    }
  })
  router.afterEach((to) => {
    
    
  	//设置标题
    document.title = getPageTitle(to.meta.title)
  })
}

(2)var文件引用

在这里插入图片描述

export function setupVab (app: any) {
    
    
  // 加载插件
  const Plugins = require.context('./plugins', true, /\.ts$/)
  Plugins.keys().forEach((key) => Plugins(key).setup(app))
}

(3)将在main中添加调用,由于我封装到permissions.ts文件中,通过var文件调用

import {
    
     createApp } from 'vue'
import App from './App.vue'
import {
    
     setupVab } from '@/vab'

const app = createApp(App)
setupVab(app)

(4) setRoutes方法:存储vuex中routes,合并路由列表

async setRoutes ({
    
     commit }: {
    
     commit: any }, mode = 'none') {
    
    
    // 默认前端路由
    const routes = [...asyncRoutes]
    // 设置游客路由关闭路由拦截
    const control = mode === 'visit' ? false : rolesControl
    // 后端路由
    // if (authentication === 'all') {
    
    
    //   const { data } = await getRouterList()
    //   const { list } = data
    //   if (!isArray(list))
    //     gp.$baseMessage(
    //       '路由格式返回有误!',
    //       'error',
    //       false,
    //       'vab-hey-message-error'
    //     )
    // if (list[list.length - 1].path !== '*') {
    
    
    //   list.push({
    
    
    //     path: '/:pathMatch(.*)*',
    //     redirect: '/404',
    //     name: 'NotFound',
    //     hidden: true
    //   })
    //   routes = convertRouter(list)
    // }
    // 根据权限和rolesControl过滤路由
    const finallyRoutes = filterRoutes([...constantRoutes, ...routes], control)
    // // 设置菜单所需路由
    commit('setRoutes', finallyRoutes)
    // // 根据可访问路由重置Vue Router
    await resetRouter(finallyRoutes)
  },

(5)filterRoutes:根据权限和rolesControl过滤路由

export function filterRoutes (routes:any, rolesControl:any, baseUrl = '/') {
    
    
  return routes
    .filter((route:any) => {
    
    
      if (rolesControl && route.meta && route.meta.roles) {
    
    
        return hasAccess(route.meta.roles)
        return false
      } else {
    
     return true }
    })
    // .map((route) => {
    
    
    //   if (route.path !== '*' && !isExternal(route.path))
    //     route.fullPath = resolve(baseUrl, route.path)
    //   if (route.children)
    //     route.children = filterRoutes(
    //       route.children,
    //       rolesControl,
    //       route.fullPath
    //     )
    //   return route
    // })
}

(6)toLoginRoute:

/**
 * 获取当前跳转登录页的Route
 * @param currentPath 当前页面地址
 */
export function toLoginRoute (currentPath:any) {
    
    
  if (recordRoute && currentPath !== '/') {
    
    
    return {
    
    
      path: '/login',
      query: {
    
     redirect: currentPath },
      replace: true
    }
  } else {
    
    
    return {
    
     path: '/login', replace: true }
  }
}

4、创建router.js 文件,创建路由列表和添加路由的方法

设置默认路由和模拟请求后添加的路由,定义添加路由的方法

// 定义路由和路由添加的方法
import {
    
     createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import configOb from '@/config'
import {
    
     getNames } from '@/utils/routes'

//设置默认数组
export const constantRoutes = [
  {
    
    
    path: '/login',
    name: 'Login',
    component: () => import('@/views/login/index.vue'),
    hidden: true
  },
  {
    
    
    path: '/403',
    name: '403',
    component: () => import('../views/403.vue'),
    hidden: true
  },
  {
    
    
    path: '/404',
    name: '404',
    component: () => import('../views/404.vue'),
    hidden: true
  }
]

//假设请求的到的数组
export const asyncRoutes = [
  {
    
    
    path: '/',
    name: 'Root',
    // component: Layout,
    redirect: '/index',
    meta: {
    
    
      title: '平台首页',
      icon: 'iconfont icon-ptsyy icon-white'
    },
    children: [
      {
    
    
        path: 'index',
        name: 'Index',
        component: () => import('../views/index/index.vue'),
        meta: {
    
    
          title: '首页',
          icon: 'home-2-line',
          noClosable: true
        }
      }
    ]
  },
  {
    
    
    path: '/error',
    name: 'Error',
    // component: Layout,
    redirect: '/error/403',
    menuHidden: true,
    meta: {
    
    
      title: '错误页',
      icon: 'error-warning-line'
    },
    children: [
      {
    
    
        path: '403',
        name: 'Error403',
        component: () => import('../views/403.vue'),
        meta: {
    
    
          title: '403',
          icon: 'error-warning-line'
        }
      },
      {
    
    
        path: '404',
        name: 'Error404',
        component: () => import('../views/404.vue'),
        meta: {
    
    
          title: '404',
          icon: 'error-warning-line'
        }
      }
    ]
  },
  {
    
    
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    name: 'NotFound',
    hidden: true
  }
]

//是否开启hash模式
const {
    
     isHashRouterMode, publicPath } = configOb
const router = createRouter({
    
    
  history: isHashRouterMode
    ? createWebHashHistory(publicPath)
    : createWebHistory(publicPath),
  routes: constantRoutes
})

/**
 * 添加路由
 * @param routes
 */
function addRouter (routes:any) {
    
    
  routes.forEach((route:any) => {
    
    
    if (!router.hasRoute(route.name)) router.addRoute(route)
    if (route.children) addRouter(route.children)
  })
}

export default router

猜你喜欢

转载自blog.csdn.net/m0_50207524/article/details/130314864