草庐IT

vue3+动态路由

八怪iii 2023-11-20 原文

         动态路由,也就是不是写死的路由,根据自己的需求加载不同的页面;现在很多的后台管理项目就是根据用户角色的不同分配不同的功能菜单(页面);

        根据用户登录的角色返回可以访问的页面路由,前端将路由存储到 pinia 实现持久话存储,然后在路由前置守卫用 addRoute 动态添加路由,对页面进行渲染。

        通常的实现步骤:

  1. 前端调用登录接口获取用户ID(uid)         
  2. 前端用uid请求接口获取路由表(JSON)
  3. 对路由表进行数据格式话形成树形结构
  4. 树形结构 转 vue路由结构
  5. 路由结构 转  静态路由
  6. 树形结构 转  菜单组件

 下面是我练习一个demo,仅用于学习与记录;

服务端代码结构:

         服务端在本地localhost:3007,

 


 server.js

//导入express 模块
const express = require("express")
//创建 express 实例
const app = express()
//导入cors 中间件
const cors = require("cors")
app.use(cors())
//配置表单解析中间件
app.use(express.urlencoded({extended:false}))

const useRouter = require("./router/index.js")

app.use("/api",useRouter)
app.listen(3007,function (){
    console.log("api server running at http://127.0.0.1:3007")
})

 router/index.js

const express = require("express")
const router = express.Router()
const users = require("../mockDB/user.js")
const routers = require("../mockDB/router.js")


router.post("/routers", (req, res) => {
    const {uid} = req.body
    if (uid) {
        let authRouterInfo;
        authRouterInfo = [];
        const userInfo = users.find(user => user.id === JSON.parse(uid))
        console.log(users)
        userInfo.auth.map((rid) => {
                routers.map((router) => {
                    if (router.id === rid) {
                        authRouterInfo.push(router)
                    }
                })
        })
        res.send({
            status: 0,
            msg: "post 请求成功",
            data: authRouterInfo
        })

    } else {
        res.send(
            {
                status: 0,
                msg: "查询不到此uid !",
                data: null
            }
        )
        }
    }
)
    module.exports = router

mockDB/user.js

module.exports = [
    {
        id:1,
        name:"zhangsan",
        auth:[2,3,6,7]
    },
    {
        id:2,
        name:"lisi",
        auth:[2,3,5,6,7,8]
    },
    {
        id:3,
        name:"wangwu",
        auth:[2,3,4,5,6,7,8]
    },
    {
        id:4,
        name:"mazi",
        auth:[6,7,8]
    }
]

mockDB/router.js 

module.exports = [
    {
        id:2,
        pid:0,
        path:"/course",
        name:"Course",
        title:"课程管理"
    },
    {
        id:3,
        pid:2,
        path:"operate",
        name:"CourseOperate",
        title:"课程操作",
        link:"/course/operate"
    },
    {
        id:4,
        pid:3,
        path:"info_data",
        name:"CourseInfoData",
        title:"课程数据",
        link:"/course/operate/info_data"
    },
    {
        id:5,
        pid:2,
        path:"add",
        name:"CourseAdd",
        title:"课程添加",
        link:"/course/add"
    },
    {
        id:6,
        pid:0,
        path:"/student",
        name:"Student",
        title:"学生管理"
    },
    {
        id:7,
        pid:6,
        path:"operate",
        name:"StudentOperate",
        title:"学生操作",
        link:"/student/operate"
    },
    {
        id:7,
        pid:6,
        path:"add",
        name:"StudentAdd",
        title:"学生增加",
        link:"/student/add"
    }
]

 前端代码结构:

         前端调用 /api/routers 传入 uid 获取用户路由表

调用接口

import axios from "axios"
import qs from "qs"
export function getRouters(uid){
    return  axios({
        url:"http://127.0.0.1:3007/api/routers",
        method:"post",
        header:{
            "Content-type":"application/x-www-from-urlencoded"
        },
        data:qs.stringify({uid})
    })
}

 将路由表格式成树结构, 路由表结构mockDB/router.js

export function formatRouterTree(datas) {
    let res = []
    datas.map(data => {
        // data.children = []
        //console.log(data.children)
        if (data.pid === 0) {
            res.push(data)
        } else {
            add2Tree(data, res)
        }
    })
    return res

}

function add2Tree(data, res) {
    res.map(r => {
        if (data.pid === r.id) {
            if (!r.children) r.children = []
            r.children.push(data)
        } else {
            if (r.children)
                add2Tree(data, r.children)
        }
    })

}

树结构 转 vue路由结构

export function generateRouter(userRouters) {
    let newRouters;
    newRouters = userRouters.map(r => {
        let routes = {
            path: r.path,
            name: r.name,
            component: () => import(`../view/${r.name}.vue`)
        }
        if (r.children) {
            routes.children = generateRouter(r.children)
        }
        return routes
    });
    return newRouters
}

先配置静态的路由,接着添加动态路由  ==> router/route.js

const routes = [
    {
        path:"/",
        name:"Home",
        component:() => import ("../view/Home.vue")
    },
    // {
    //     path:"/404",
    //     name:"NotFound",
    //     component:() => import ("../view/NotFound.vue")
    // },
    // {
    //     path:"/:pathMatch(.*)",
    //     redirect:"/404"
    // }
]
export default routes;

router.beforeEach(async (to, from, next) => {
    const store = useRouterStore()
    if (!store.hasAuth) {
        await store.getRoutersList()
        let newRoutes = generateRouter(store.userRouters)
        let a = [...newRoutes,
            {
                path: "/404",
                name: "NotFound",
                component: () => import ("../view/NotFound.vue")
            },
            {
                path: "/:pathMatch(.*)",
                redirect: "/404"
            }]
        a.forEach((r) => {
            router.addRoute(r)
        })
        next({...to, replace: true})
        console.log(a)
    }else {
        if(to.name === null){
            next("/404")
        }
        next()
    }

})

递归组件模版渲染菜单组件

有关vue3+动态路由的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  3. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  5. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  6. ruby-on-rails - 如何在 Rails 中设置路由的默认格式? - 2

    路由有如下代码:resources:orders,only:[:create],defaults:{format:'json'}resources:users,only:[:create,:update],defaults:{format:'json'}resources:delivery_types,only:[:index],defaults:{format:'json'}resources:time_corrections,only:[:index],defaults:{format:'json'}是否可以使用1个字符串为所有资源设置默认格式,每行不带“默认值”散列?谢谢。

  7. ruby - 在 Ruby 中动态创建数组 - 2

    有没有办法在Ruby中动态创建数组?例如,假设我想遍历用户输入的书籍数组:books=gets.chomp用户输入:"TheGreatGatsby,CrimeandPunishment,Dracula,Fahrenheit451,PrideandPrejudice,SenseandSensibility,Slaughterhouse-Five,TheAdventuresofHuckleberryFinn"我把它变成一个数组:books_array=books.split(",")现在,对于用户输入的每一本书,我想用Ruby创建一个数组。伪代码来做到这一点:x=0books_array.

  8. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  9. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

  10. ruby - 在 Ruby 中动态生成多维数组 - 2

    我正在尝试动态构建一个多维数组。我想要的基本上是这样的(为简单起见写出来):b=0test=[[]]test[b]这给了我错误:NoMethodError:undefinedmethod`test=[[],[],[]]而且它工作正常,但在我的实际使用中,我不会事先知道需要多少个数组。有一个更好的方法吗?谢谢 最佳答案 不需要像您正在使用的索引变量。只需将每个数组附加到您的test数组:irb>test=[]=>[]irb>test[["a","b","c"]]irb>test[["a","b","c"],["d","e","f"]]

随机推荐