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

news2024/11/15 17:18:38

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

  • 前言
  • 2. 实现
    • 1、登录页面创建登录函数和watch监听路由
    • 2、调用的login方法
      • (1)登录方法
      • (2)存储token
    • 3、router.push的时候调用路由守卫
      • (1)创建路由守卫,建议路由守卫封装为单独的文件
      • (2)var文件引用
    • (3)将在main中添加调用,由于我封装到permissions.ts文件中,通过var文件调用
      • (4) setRoutes方法:存储vuex中routes,合并路由列表
      • (5)filterRoutes:根据权限和rolesControl过滤路由
      • (6)toLoginRoute:
    • 4、创建router.js 文件,创建路由列表和添加路由的方法

前言

本篇讲解的路由实现方案:默认存在的路由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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/459045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL Community Server 8.0.33安装教程【笔记】

仅安装MySQL Community Server 下载网址:https://dev.mysql.com/downloads/installer/ 1、下载对应版本; 2、下载后,双击安装,弹出界面选择【Custom】; 3、弹出界面选择【MySQL Server 8.0.33 - X64】; 3、弹出界面…

【C++ Metaprogramming】0. 在C++中实现类似C#的泛型类

两年前,笔者因为项目原因刚开始接触C,当时就在想,如果C有类似C#中的泛型限定就好了,能让代码简单许多。我也一度认为: 虽然C有模板类,但是却没办法实现C#中泛型特有的 where 关键词: public c…

Android 13 wificond讲解

wificond介绍 看如下图,可以知道wificond 进程,该进程位于 system/connectivity/wificond 中。wificond 进程通过标准的 nl80211 命令与 Wi-Fi 驱动程序进行通信。 查看手机也能看到wificond 进程 wificond启动 1. 开机的时候通过调用wificond.rc文件启动wificond system…

docker 部署LNMP

准备工作。 #首先获取nginx配置文件 [rootlocalhost ~]# docker pull nginx:1.23.3 [rootlocalhost ~]# docker run --name nginx --restartalways -d -p 80:80 nginx:1.23.3 [rootlocalhost ~]# mkdir -p /usr/local/nginx/{conf,log,html,conf.d} #复制配置文件 [rootlocalh…

易观千帆 | 2023年3月证券APP月活跃用户规模盘点

易观:2023年3月证券服务应用活跃人数14131.58万人,相较上月,环比增长0.61%,同比增长0.60%;2023年3月自营类证券服务应用Top10 活跃人数6221.44万人,环比增长0.08%;2023年3月第三方证券服务应用T…

使用Spring的五大类注解读取和存储Bean

目录 1.存储Bean对象的注解 1.1 五大类注解 1.2 方法注解 1.3添加注解的依赖 2.注解的使用 2.1 controller注解 2. 2Service注解 2.3.Resopsitory注解 2.4Component注解 2.5Configuration注解 2.6 注解之间的关系 3.方法注解 3.1 方法注解要配合类注解来使用。 3.2…

【Python】ddddoc进行OCR识别和目标检测 ——识别验证码和滑块(安装部署+测试代码注释详细)

目录 安装部署gitee已经上传完整项目requiremen.txt插件作者更新地址 项目结构第一部分 OCR识别部分第二部分 目标检测部分总结 欢迎关注 『Python』 系列,持续更新中 欢迎关注 『Python』 系列,持续更新中 安装部署 gitee已经上传完整项目 requiremen.…

图片对象列表查询与展示(vue+springboot+elementUI)

本文描述场景为 展示:后端从数据库中查询图片对象列表,返回前端展示 多图片展示 先看一下后端表实体 import com.zpmc.common.domain.BaseEntity; import io.swagger.annotations.ApiModel; import lombok.*;import javax.persistence.*; import java.…

8086汇编之乘法指令MUL

2023年4月22日,周六晚上。 今天写汇编作业的时候,碰到了MUL指令,于是把学习到的MUL指令知识记录下来,也可以通过写这篇博客彻底理清MUL指令。 当被乘数和乘数都是8位时: 怎么判断被乘数和乘数是不是8位的&#xff1f…

操作系统之认识进程

目录 什么是进程 进程的状态和转换 进程控制 进程通信 什么是进程 在电脑的任务管理器中,能看到电脑当前运行着的所有进程 那到底什么是进程呢?和我们所看所写的那些程序有什么区别? 操作系统是如何区分这些进程的呢? 那就需要…

银河麒麟(桌面版和服务器版)之远程桌面安装

一、前言 在信创方案中经常介绍支持麒麟系统,实际上麒麟分为银河麒麟和中标麒麟,银河麒麟又分为服务器版和桌面版,服务器器版一般用于应用系统部署,桌面版一般用于日常办公。银河麒麟操作系统作为国产操作系统,是目前国…

java定时任务schedule

在 Java中,可以使用定时任务(schedule)来实现定时任务。这种定时任务能够根据用户的需求进行时间的控制,让用户可以自由设定每一个任务的开始时间和结束时间。 下面来介绍如何使用 java中的定时任务来实现定时任务。 首先需要在配…

# 将pg日志导入pg数据库的几种方法

将pg日志导入pg数据库的几种方法 文章目录 将pg日志导入pg数据库的几种方法1 方法1:官方方法(fiel_fdw)1.1 创建file_fdw数据源(在此之前需要安装pg的file_fdw扩展)1.2 创建外部表并导入数据 2 方法2:用csv…

会议论文与期刊论文的写作差异

AI领域的会议论文和期刊论文在撰写方法上存在一定的差异,读者需要理解这些差异,才能做到有的放矢,提高论文的命中率。如果按照会议论文的风格来写期刊论文,或者按照期刊论文的风格来写会议论文,论文命中的概率将大大降…

服务(第十三篇)lvs(负载均衡器)+nginx(反向代理)+tomcat(后端服务器)+nfs共享

准备6台机器: 192.168.169.10 lvs负载均衡器 192.168.169.20、192.168.169.30 nginx反向代理 192.168.169.40(tomcat多实例)192.168.169.50(tomcat) 19.168.169.60(nfs共享) 实验没啥好说的…

新建项目提交到git指定仓库

新建的项目如何上传到git远程仓库: 1:首先进入需要上传的文件夹,鼠标右键点击Git Bash Here 2:输入git init,初始化git相关配置文件 git init3:输入git remote add origin 你的远程仓库地址,…

收废品小程序的推广策略与实践

随着互联网和移动设备的普及,各种小程序逐渐成为了人们生活中不可或缺的一部分。在这样的背景下,开发一个收废品小程序是一个具有巨大潜力的创意。本文将介绍如何开发一个收废品小程序,并分享一些推广策略和实践经验。 开发一个收废品小程序…

推荐好用的数据库软件sql studio

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言免费功能强大支持数据导入和导出和navicat功能相同 一、sql studio是什么?二、使用步骤1.下载软件2. window版本3.linux 版本配置方式3.如何使用sql…

论文浅尝 | 基于交互模态融合的多模态知识图谱补全

笔记整理:张溢驰,浙江大学硕士,研究方向为多模态知识图谱 链接:https://arxiv.org/abs/2303.10816 动机 多模态知识图谱补全需要将多种模态的信息(如图像和文本)融入到实体的结构表示中,以此来实…

OpenAI ChatGPT 能取代多少程序员的工作?导致失业吗?

阅读原文:https://bysocket.com/openai-chatgpt-vs-developer/ ChatGPT 能取代多少程序员的工作?导致我们程序员失业吗?这是一个很好的话题,我这里分享下: 一、ChatGPT 是什么?有什么作用 ChatGPT是一种…