0


后台管理系统 - 页面布局设计

前端的中后台管理系统相比于其他普通项目,从开发设计的角度来说有几点比较特殊:

  • 一个是权限设计,具体实现可参考:传送门。
  • 一个是页面布局的设计,也是本文要说的。一个好的页面布局设计,无论是对于页面结构的稳定性,还是功能拓展的方便性,亦或是用户体验上,都有着重要的作用。

一、市面参考

先来看看市面上的一些优秀的开源系统项目的页面布局。

1、vue-element-admin

vue-element-admin 是 vue 框架的一个优秀的后台管理系统开源项目,目前star数75k。

vue-element-admin采用的是侧边菜单布局,侧边菜单 + 顶部导航 + 内容区域,这也是我个人最推崇的布局方式。

2、ant design pro

ant design pro 有提供三种布局。

(1)顶部菜单布局

即:顶部导航菜单 + 内容区域。

这种方式布局简单,但缺点很明显,菜单都挤在顶部导航区域,在菜单项越来越多时就放不下了,很难处理,可扩展性不强。

(2)侧边菜单布局

侧边菜单 + 顶部导航 + 内容区域。

同vue-element-admin类似,主要区别就是antd pro的面包屑导航是另起一行单独放的,这样挤压了内容区域的空间,个人觉得还是放在顶部和右上角的快捷按钮放同一行最好。

(3)混合菜单布局

其实和侧边菜单布局大同小异,还是属于侧边菜单布局的范畴。

只不过这样布局的话,面包屑导航就不适合和顶部放一行了,只能另起一行。

二、选型

参考市面上比较优秀的两款项目模板的布局后,个人还是觉得vue-element-admin的布局方式更胜一筹。

文本就围绕这种布局结构来设计。

  • 示例项目:react-antd-mobx-admin
  • 技术栈:react 17 + antd 4 + react-router-dom 6 + ts
  • 路由统一管理使用 react-router-waiter 方案

效果图:

其实技术选型不那么重要,无论是react还是vue,element或是antd,思路一致,都只是实现代码的差异而已。

对于侧边栏菜单和面包屑导航,element和antd都有相应的组件可以直接使用,其他的手写实现。

三、css布局

良好的css布局代码才能保证页面布局的稳定性。

而对于整体布局来说,flex是首选,稳定性更好,不兼容ie9。

这里将整体布局封装成组件

PageLayout

(1)首先,设置侧边栏右侧的盒子撑满屏幕剩余宽度。
flex布局有个特性是:只对一个子元素设置

flex: 1

属性时,该子元素默认会撑满父容器的剩余空间。

.c-PageLayout-index{width: 100%;height: 100%;display: flex;

  .appMainWrap{height: 100%;flex: 1; // 占据屏幕剩余宽度
    position: relative;padding-top: 50px; // 留出顶部导航栏区域,顶部导航栏使用悬浮置顶。
  }.appMain{height: 100%;overflow: auto;padding: 15px; // 内容区域可以在这里统一设置下边距
  }}
  • c-PageLayout-index 页面整体容器
  • appMainWrap 侧边栏右侧的(顶部导航区域 + 内容区域)容器
  • appMain 内容区域容器

(2)侧边菜单区域默认撑满高度,宽度可交给antd组件自适应,也可以自己设死。

.c-PageLayout-sideBar{height: 100%;overflow: auto;}

(3)顶部导航区域悬浮置顶。

.c-PageLayout-headBar{height: 50px;display: flex;justify-content: space-between;position: absolute;top: 0;right: 0;width: 100%;}

四、侧边栏菜单

侧边栏的实现方式是难点,因为这里即涉及到如何和路由数据匹配,又涉及权限的筛选。

侧边栏最好是和路由配置共用一套数据,方便扩展和维护,这里得益于 react-router-waiter 已经封装好的路由管理方案(类vue-router),所以直接读取路由配置数据,动态生成菜单组件结构。

路由配置数据:

import PageLayout from'@/components/PageLayout'import{ HomeOutlined }from'@ant-design/icons'const routes: RoutesTypeNew =[{
    path:'/',
    element:<PageLayout />,
    children:[{
        path:'index',component:()=>import(/* webpackChunkName: "index" */'@/views/index/index'),
        meta:{
          title:'首页',
          icon:<HomeOutlined />,
          accessId:'10000',}},]},]
  • 如有点击跳转外链的菜单场景,可以在routes里添加个自定义的配置对象,例如通过url属性指代外链地址。

动态生成菜单:

// 递归获取层级菜单functiongetMenuList(){const getList: any =(routeList =[], prePath ='')=>{let menuList:JSX.Element[]=[]
    routeList.forEach((v: RoutesItemTypeNew)=>{if(v.path ==='/'){
        menuList = menuList.concat(getList(v.children,'/'))}else{const currentPath = prePath + v.path
        if(v.children){
          menuList.push((<SubMenu key={currentPath} icon={v.meta.icon} title={v.meta.title}>{getList(v.children, currentPath +'/')}</SubMenu>))}else{
          menuList.push((<ItemMenu key={currentPath} icon={v.meta.icon}><Link to={currentPath}>{v.meta.title}</Link></ItemMenu>))}}})return menuList
  }returngetList(routes)}
  • 如需要对权限路由做筛选,通过在路由配置数据meta里添加accessId字段作为路由权限id,然后在遍历routeList时,读取该accessId做权限判断。

五、面包屑导航

要使用面包屑导航,需要对路由路径配置有一定的约束规则,即,配置path路径时不要随意使用斜杠

/

划分,只通过嵌套路径自动划分路径。

这样才能对路由完整路径通过

/

分隔并匹配,来生成对应的面包屑导航数据。

首先,写个方法,遍历路由,生成路由路径和路由meta字段的映射数据:

functiongetRouteMetaMap(){const getMap: any =(routeList =[], prePath ='')=>{let map ={}
    routeList.forEach((v: RoutesItemTypeNew)=>{let currentPath = prePath + v.path
      if(v.path ==='/'){
        currentPath =''}else{
        map ={...map,[currentPath]: v.meta ||{}}}if(v.children){
        map ={...map,...getMap(v.children, currentPath +'/')}}})return map
  }returngetMap(routes)}
  • 映射数据示例:{"/index":{"title":"首页","accessId":"10000"},"/nest":{"title":"多级菜单",},"/nest/nest1":{"title":"二级菜单1"},"/nest/nest1/nest11":{"title":"三级菜单11"}}

然后,获取当前路由完整路径(例如:

/nest/nest1/nest11

),再通过

/

分隔成多段子路由,和上述getRouteMetaMap方法取到的映射数据匹配,获取子路由的title标题组合成面包屑(多级菜单 / 二级菜单1 / 三级菜单11),展示出来。

const routeMetaMap =getRouteMetaMap()const pathSnippets = location.pathname.split('/').filter(i=> i)const extraBreadcrumbItems = pathSnippets.map((_, index)=>{const url =`/${pathSnippets.slice(0, index +1).join('/')}`return(<Breadcrumb.Item key={url}><span>{routeMetaMap[url].title}</span></Breadcrumb.Item>)})

本文示例项目源码:react-antd-mobx-admin


参考链接:
https://panjiachen.gitee.io/vue-element-admin/
https://preview.pro.ant.design/form/basic-form

标签: vue.js 前端 react.js

本文转载自: https://blog.csdn.net/u010059669/article/details/123528995
版权归原作者 醉逍遥neo 所有, 如有侵权,请联系我们删除。

“后台管理系统 - 页面布局设计”的评论:

还没有评论