首页 > 其他分享 >vue3 + vite4 + vue-router4动态路由存在的问题

vue3 + vite4 + vue-router4动态路由存在的问题

时间:2023-02-27 10:11:06浏览次数:54  
标签:vue return vue3 router4 item token import path children

使用vite4、vue3、vue-router4搭建动态路由的时候遇到的问题及解决方法解决!!

我使用的是登录接口返回菜单,使用pinia存储菜单数据,使用pinia-plugin-persist加js-cookie进行持久化存储数据

以下是我运行正常的代码

  1. 存储登录信息的store(useLogin)
  // useLogin.js
  import { defineStore } from 'pinia'
  import { cookiesStorage } from '../utils'

  export const useLogin = defineStore("useLogin", {
      state() {
          return {
              token: '',
              menus: []
          }
      },
      getters: {
          getToken() {
              return this.token
          }
      },
      actions: {
          setLoginInfo({ token = '', menus = [] }) {
              this.token = token
              this.menus = menus
          }
      },
      persist: {
          enabled: true,
          strategies: [
              {
                  storage: cookiesStorage,
                  paths: ['token', 'menus']
              },
          ]
      }
  })
  1. utils.js
 // utils.js
  import Cookies from "js-cookie";
  const modules = import.meta.glob("../views/**/**.vue");

    export const cookiesStorage = {
        setItem(key, state) {
            return Cookies.set(key, state, { expires: 3 })
        },
        getItem(key) {
            return Cookies.get(key)
        }
    }

    /**
     * 
     * @param {Array} children chilren路由
     * @param {Object} item 当前路由
     * @returns import
     */
    function showRouterView(children, item) {
        let hasChildren = children.length > 0
        let allHidden = hasChildren && children.every(it => it.hidden)
        if (allHidden || children.length === 0) {
            return modules[`../views${item.path}.vue`]
        }
        return () => import(/* @vite-ignore */ `../components/parentRoute/parentRoute.vue`)
    }

    /**
     * 路由扁平化转换为tree
     * @param {*} routes // 路由
     * @param {*} pid // 对应父级的id,0为没有父路由
     */
    export function generatorRoute(routes, pid = 0) {
        let children = routes.filter(it => it.pid === pid)
        if (!children.length) {
            return []
        }
        let routers = children.map(item => {
            let children = generatorRoute(routes, item.id)
            let node = {
                name: item.name || "",
                path: item.path,
                meta: {
                    hidden: !!item.hidden,
                    title: item.title,
                    icon: item.icon || ""
                },
                component: showRouterView(children, item),
            }
            return {
                ...node,
                children
            }
        })
        return routers
    }
  1. 登录返回的数据
   [{
        id: 1,
        pid: 0,
        path: '/admin/userList',
        hidden: false,
        name: 'admin',
        icon: 'User',
        title: '用户管理'
    }, {
        id: 2,
        pid: 1,
        name: 'user',
        path: '/admin/userList',
        title: '用户列表'
    }, {
        id: 2,
        pid: 0,
        name: 'system',
        path: '/system/system',
        hidden: true,
        title: '系统管理'
    }]
  1. 静态路由
    import Layout from '@/layout/index.vue'
    export default [{
      path: '/login',
      name: 'login',
      component: () => import("@/views/Login.vue")
    },
    {
      path: '/',
      component: Layout,
      name: 'Layout',
      redirect: '/home/home',
      children: [{
        path: '/home/home',
        name: 'home',
        component: () => import("@/views/home/home.vue")
      }]
    },
    {
      path: '/:pathMatch(.*)*',
      name: 'notFund',
      component: () => import("@/views/notFund/notFund.vue")
    }]
  1. permission.js
  // import pinia from '../stores/piniaInstance'

  import router from './index'
  import { useLogin } from '@/stores/useLogin'
  import { generatorRoute } from '../utils'
  const LOGIN_PATH = '/login'

  router.beforeEach((to, from) => {
      let store = useLogin()
      let menus = store.menus
      let token = store.token
      // 已登录,不是登录页面
      if (token && to.path !== LOGIN_PATH) {
          let hasRoute = menus.length > 0 && router.hasRoute(menus[0].name)
          // 没有添加过路由
          if (!hasRoute) {
              let routes = generatorRoute(menus)
              routes.forEach(it => {
                  router.addRoute("Layout", it)
              })
              router.replace(to.path)
          }
      } else if (token && to.path === LOGIN_PATH) {
          // 已经登录,是登录页面
          return { path: '/', replace: true }
      } else if (!token && to.path !== LOGIN_PATH) {
          // 没有登录,不是登录页面
          return { path: LOGIN_PATH, replace: true }
      }
  })

标签:vue,return,vue3,router4,item,token,import,path,children
From: https://www.cnblogs.com/skystudy/p/17158718.html

相关文章

  • 说说Vue响应式系统中的Watcher和Dep的关系-面试进阶
    引言在这里我先提出两个问题(文章末尾会进行解答):在Vue的数据响应系统中,Dep和Watcher各自分担什么任务?Vue的数据响应系统的核心是Object.defineproperty一定是最好的吗?有......
  • 前端一面常见vue面试题汇总
    说说你对proxy的理解,Proxy相比于defineProperty的优势Object.defineProperty()的问题主要有三个:不能监听数组的变化:无法监控到数组下标的变化,导致通过数组下标添......
  • 能不能手写Vue响应式?前端面试进阶
    Vue视图更新原理Vue的视图更新原理主要涉及的是响应式相关APIObject.defineProperty的使用,它的作用是为对象的某个属性对外提供get、set方法,从而实现外部对该属性的......
  • 阿里前端常考vue面试题汇总
    Vuex中actions和mutations有什么区别题目分析mutations和actions是vuex带来的两个独特的概念。新手程序员容易混淆,所以面试官喜欢问。我们只需记住修改状态只能是mutat......
  • vue 生命周期
    生命周期钩子每个Vue组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到DOM,以及在数据改变时更新DOM。在此过程中,它也会运行被称为......
  • Vue 兼容性问题 Vue-cli3.x/4.x 兼容低版本浏览器的方案
    参考资料:https://blog.csdn.net/sinat_41292836/article/details/116499810 babel.config.jsmodule.exports={presets:[['@vue/app',......
  • Vue 3
    Vue(发音为/vjuː/,类似 view)是一款用于构建用户界面的JavaScript框架。Vue的两个核心功能:声明式渲染:Vue基于标准HTML拓展了一套模板语法,使得我们可以声明式......
  • 在vue3+vite3中使用socket.io-client踩坑记录
    1版本问题服务端socket.io版本和client端一定要对应,否则会连接不上。前端封装业务逻辑之前,要去和后台首先确定下自己团队所需要采用的版本。2低版本socket.io-client和v......
  • vue3动态组件
    markRow:标记一个对象,使其不能成为一个响应式对象。toRaw:将响应式对象(由reactive定义的响应式)转换为普通对象。shallowRef:只处理基本数据类型的响应式,不进行对象的响应式......
  • vue3异步组件(defineAsyncComponent、Suspense的使用)
    异步组件按需引入,用到的时候再加载,异步组件的引入需要用​​defineAsyncComponent​​进行注册。​​defineAsyncComponent​​工厂函数需要返回一个Promise对象,接收对象类......