4.侧边菜单栏

一、页面整体布局

  使用el-container布局容器,这里重点在样式上。

二、菜单栏制作

2.1目录划分结构 

  如果按照login界面的设计进行目录结构划分--main-cpns,但我们main里面其实有很多组件内容,这种是不适合的。

 2.2侧边菜单栏标题制作

 

 2.3侧边栏菜单内容制作

  使用el-menu组件(类似于el-sub-menu,el-menu都是可以展开的,而el-sub-item是不可以展开的)。我们这里要对userMenus进行展示,查看知这是一个数组,可以采用template遍历的方式展示。

2.3.1拿到userMenus数据

  可以通过$store.state.login.userMenus拿到login模块的数据,但这种做法不好。

   更好的方法是用一个计算属性,但是你会发现直接写state没有类型现在。那怎么办?我不用vuex默认的useStore,我自己在store-inex.ts中导出一个useStore(其实就是把vuex的useStore重新封装了一下,加了一些类型限制)

 

 

 2.3.2数据展示

  根据接口文档分析,当type==1,可以展开的菜单,type==2,不可以展开的菜单,使用template模板进行if判断。

  • 首先来看一下示例:

  •  我也用了index,其他结构完全符合要求,但是无论点击哪一个就全部展开或全部关闭

  •  但是后面页面正常了,却报了特别多的警告。这是因为要求我们传入index是一个字符串类型,但我们的id是number类型,可以通过item.id + ''转为字符串。就没有警告啦!
  • 另外图标因为element-plus更新了图标引入方法,所以不能通过遍历引入了!

 三、面包屑制作--实现点击菜单栏隐藏和展示

3.1搭建结构

和nav-menu的结构搭建过程类似。

3.2功能实现

要求:有展开和折叠两个按钮,当菜单展开时,折叠按钮显示;当菜单折叠时,展开按钮显示。点击折叠按钮,菜单折叠,点击展开按钮,菜单展开。el-menu有一个默认属性collapse表示菜单的折叠和展开。

解决:首先设置图标大小样式,小手。绑定点击事件。

 

 问题1:现在有一个难点是怎么实现nav-menu和nav-header之间的通信,将isCollapse传到nav-menu中?因为它们不是父子关系哦!

 非父子组件的通信:(Vue3组件化开发(二))

方式1:Provide/Inject

方式2:Mitt全局事件总线

解决:使用Mitt事件总线是可以的(没试过啊!)。这里采用将isCollapse传到nav-menu和nav-header的公共父组件main中,nav-menu再从main中拿到这个属性对el-menu进行操作。那为什么要这么做呢?因为main里面有el-aside的宽度设置啊!

setup函数的参数:(Vue3-Composition-API)

setup函数主要有两个参数:

1.props:父组件传递过来的属性会放在props对象中,如果需要使用就通过props参数获取

2.context,包括三个属性①attrs所有的非props的attribute,比如id,class;②slots父组件传递过来的插槽;③emit当组件内部需要发出事件时会用到emit

具体代码:

 

 还要再el-aside中对width进行动态绑定哦!

 通过ref定义的数据切记通过.value获取!

 mian向nav-menu(父--子通信)

 

 问题2:文字显示不正确

 很简单

 四、动态路由实现(重点--不同角色对应不同的权限--有不一样的菜单)

 RBAC:role based access control 基于角色的访问控制(如果根据不同用户对应不同权限,会很复杂;可以采用不同角色对应不同权限)

 每一个用户都对应着自己的角色,每一个角色都有自己的菜单。所以菜单不能写死,那么怎么注册动态路由呢?

  • 方案一:如果我们把所有的动态路由都注册了,虽然可以根据不同用户的菜单进行显示,但是会有一个风险:如果用户手动修改了url,那我们注册的组件依然会被显示。
  • 方案二:也可以通过:

 这种做法的缺点是,新增角色时,需要修改前端代码,然后重新部署。

  • (本项目)方案三:根据菜单动态的生成路由映射:菜单里面有一个url,这个url对应的就是路由里面的path,那么可以让path对应一个component。
    • 法一:后端给的接口文档的菜单中本来就有加载组件的名称,比如接口文档中就有component对应Role.vue,但是这要求名称和路径必须一致。
    • (本项目)法二:后端给的接口文档的菜单中只有url,而且我们在前端代码中已经配置好了path-component之间的映射关系。根据菜单的url动态的去加载路由。

OK!现在来创建路由。可以采用手动创建的方法、但是会比较繁琐。

  • 结构划分

  •  代码

 这里使用一个自动化工具(可以去github上瞅瞅),让这些类似的代码自动生成。

1 npm install coderwhy -g
1 coderwhy add3page user -d src/views/main/system/user

  其他页面按照同样的方法生成。

接下来就是根据菜单的url去匹配路由的映射关系。有这个映射关系就把它放到某个数组中,没有就不放。匹配完成后,数组中存放的就是根据用户权限应该注册的路由。

这样路由就是动态的啦!

  • NotFound页面

很简单,自己查文档(Vue3+Ts--22VueRouter)

 下面就要根据菜单去动态加载对应的路由:

   这里的userMenus可能来自两个地方:1.用户最初登录时,来自服务器;2.来自localStorage

  可以吧userMenus到routes的映射单独写在一个地方:utils->map-menus.ts

补充知识:

require.contexte('')

require是一个对象,上面代码可以直接用,因为它属于Webpack里面的一个工具,可以加载某个文件夹。

 

 

 

 

 

 

 

 

补充知识:  

router.addRoute(parentName, route)

 

 现在路由已经动态添加了,但是点击页面发现还是没有效果。这是因为没有处理菜单的点击事件。

 

 

 

 

 

 对点击事件进行下面的处理,发现页面路径可以发生变化,但是页面还是没变。

 

 这是因为我们没有在el-main中进行占位:

 

posted @ 2021-12-13 22:52  不爱吃小红薯的小橘子  阅读(855)  评论(0)    收藏  举报