使用v-for用户菜单渲染

前端页面的菜单渲染,是项目开发中的很重要一部分,设计思路需要我们好好斟酌一下。

因为我们要根据登录用户的角色,去渲染对应的菜单。如下:

目录

一、数据库设计

[1.1 创建menu表](#1.1 创建menu表)

练习1:从menu表中,根据父菜单id(parent_id为0的那种)查询出子菜单

[1.2 创建role表](#1.2 创建role表)

[1.3 创建rolemenu表](#1.3 创建rolemenu表)

练习2:从rolemenu表,根据role_id(角色id)查询出menu_id(父菜单id)

[1.4 在user表中,填入role_id字段,来声明该用户是什么角色](#1.4 在user表中,填入role_id字段,来声明该用户是什么角色)

练习3:查询所有用户的角色名称

二、后端查取全部用户信息(携带菜单数据)

[2.1 创建实体类Menu](#2.1 创建实体类Menu)

[2.2 创建RoleMenuMapper](#2.2 创建RoleMenuMapper)

[2.3 创建MenuMapper](#2.3 创建MenuMapper)

[2.4 修改实体类User](#2.4 修改实体类User)

[2.5 在UserServiceImpl中,编写查询登录用户菜单的业务逻辑](#2.5 在UserServiceImpl中,编写查询登录用户菜单的业务逻辑)

[2.6 使用apifox,发送请求,查看返回的登录用户信息](#2.6 使用apifox,发送请求,查看返回的登录用户信息)

三、前端使用v-for渲染菜单

[3.1 使用pinia,存储登录用户的个人信息](#3.1 使用pinia,存储登录用户的个人信息)

[3.2 登录页面后,查询pinia中的登录用户信息](#3.2 登录页面后,查询pinia中的登录用户信息)

[3.3 使用pinia存储的登录用户信息中的菜单信息,渲染菜单](#3.3 使用pinia存储的登录用户信息中的菜单信息,渲染菜单)

四、查看效果

[4.1 登录角色:挂号收费员](#4.1 登录角色:挂号收费员)

[4.2 登录角色:门诊医生](#4.2 登录角色:门诊医生)

[4.3 登录角色:医技医生](#4.3 登录角色:医技医生)

[4.4 登录角色:药房操作员](#4.4 登录角色:药房操作员)

[4.5 登录角色:财务管理员](#4.5 登录角色:财务管理员)

结语


一、数据库设计

1.1 创建menu表

①menu_name:菜单名称,如:"门诊挂号收费"、"现场挂号"

②menu_icon:菜单的图标名称(来自element-plus)

③菜单对应的路由路径(vue路由),如:/registration/onsite_registration

注意:只有子菜单才有路由。而父菜单没路由信息,不跳转。

④parent_id:菜单的父菜单id,这是构成层次的关键。(两级菜单:父菜单、子菜单)。如果某个菜单是父菜单(即:该菜单没有父菜单),那么此时parent_id设为0。
根据前端页面,给menu表填充数据:

练习1:从menu表中,根据父菜单id(parent_id为0的那种)查询出子菜单

查询父菜单【门诊挂号收费】的所有子菜单:

查询父菜单【门诊医生工作站】的所有子菜单:

查询父菜单【门诊医技工作站】的所有子菜单:

查询父菜单【门诊药房工作站】的所有子菜单:

查询父菜单【门诊财务管理】的所有子菜单:

1.2 创建role表

1.3 创建rolemenu表

练习2:从rolemenu表,根据role_id(角色id)查询出menu_id(父菜单id)

1.4 在user表中,填入role_id字段,来声明该用户是什么角色

练习3:查询所有用户的角色名称

SELECT

u.*,

r.rolename

FROM

user u

JOIN

role r ON u.role_id = r.id

二、后端查取全部用户信息(携带菜单数据)

2.1 创建实体类Menu

2.2 创建RoleMenuMapper

2.3 创建MenuMapper

2.4 修改实体类User

2.5 在UserServiceImpl中,编写查询登录用户菜单的业务逻辑

java 复制代码
@Service //表明这是一个service层
public class UserServiceImpl implements UserService {
    //注入UserMapper的实例
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RolemenuMapper rolemenuMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Override
    public User login(User user) {
        //1.查询出当前登录用户loginUser
        User loginUser = userMapper.login(user);
        if(loginUser!=null){
            //2.给该用户添加菜单
            //2.1现在已知role_id,根据role_id从rolemenu表查询父菜单id
            Integer fatherMenuId = rolemenuMapper.queryMenuId(loginUser.getRoleId());
            //2.2根据fatherMenuId(父菜单id),从menu表查询出父菜单fatherMenu
            Menu fatherMenu = menuMapper.queryMenuById(fatherMenuId);
            //2.3根据fatherMenuId(父菜单id),从menu表查询出所有子菜单
            List<Menu> sonMenus = menuMapper.queryAllMenusByFatherId(fatherMenu.getId());
            //2.4将子菜单集合sonMenus,添加到父菜单fatherMenu中
            fatherMenu.setChildren(sonMenus);
            //2.5将父菜单fatherMenu,添加到登录用户user中
            loginUser.setFatherMenu(fatherMenu);
        }
        
        return loginUser;
    }
}

2.6 使用apifox,发送请求,查看返回的登录用户信息

发送请求:

响应数据:

{

"code": 200,

"message": "登录成功",

"data": {

"id": 6,

"username": "money",

"password": "123",

"avatar": null,

"nickname": "钱雷",

"roleId": 5,

"rolename": "财务管理员",

"fatherMenu": {

"id": 25,

"menuName": "门诊财务管理",

"menuIcon": null,

"menuPath": null,

"parentId": 0,

"children": [

{

"id": 26,

"menuName": "费用科目管理",

"menuIcon": null,

"menuPath": null,

"parentId": 25,

"children": null

},

{

"id": 27,

"menuName": "门诊科室工作量统计",

"menuIcon": null,

"menuPath": null,

"parentId": 25,

"children": null

}

]

}

}

}

可见此时登录的用户是"钱雷",角色是"财务管理员",拥有的菜单如下:

三、前端使用v-for渲染菜单

接下来,我们需要将后端返回的菜单数据,渲染到前端页面上。

3.1 使用pinia,存储登录用户的个人信息

3.2 登录页面后,查询pinia中的登录用户信息

登录页面时,会向后端发送登录请求,并将返回的登录用户信息存入pinia中:

3.3 使用pinia存储的登录用户信息中的菜单信息,渲染菜单

获取pinia的登录用户信息

使用登录用户的菜单信息,渲染element-plus菜单组件

html 复制代码
  <!-- 左侧菜单 -->
  <el-menu
    default-active="2"
    class="el-menu-vertical-demo"
    background-color="#143f6b"
    text-color="#fff"
    active-text-color="#ffd04b"
    @open="handleOpen"
    @close="handleClose"
  >

    <!-- 【首页】 -->
    <el-menu-item index="1">
          <el-icon><HomeFilled /></el-icon>
          <span>首页</span>
    </el-menu-item>

    <!-- 【父菜单】 -->
    <el-sub-menu index="2">
      <!--菜单标题-->
      <template #title>
        <!-- 小图标 -->
        <!-- <el-icon><location /></el-icon> -->
        <span>{{user.fatherMenu.menuName}}</span>
      </template>
      <!-- 子菜单 -->
      <!-- <el-menu-item index="2-1">现场挂号</el-menu-item>
      <el-menu-item index="2-2">收费</el-menu-item>
      <el-menu-item index="2-3">退号</el-menu-item>
      <el-menu-item index="2-4">患者费用查询</el-menu-item>
      <el-menu-item index="2-5">收费员日结</el-menu-item> -->
      <!-- 使用v-for来渲染子菜单 -->
      <el-menu-item
        v-for="childrenMenu in user.fatherMenu.children" 
        :key="childrenMenu.menuName" 
        :index="childrenMenu.menuName">
          {{childrenMenu.menuName}}
      </el-menu-item>
    </el-sub-menu>

  </el-menu>

四、查看效果

4.1 登录角色:挂号收费员

4.2 登录角色:门诊医生

4.3 登录角色:医技医生

4.4 登录角色:药房操作员

4.5 登录角色:财务管理员

结语

以上就是使用v-for渲染前端菜单的全部流程。

如果有不懂的点,可以私信博主,博主看到就会耐心解答~

喜欢本篇文章的话,可以留个免费的关注~~

相关推荐
一雨方知深秋12 天前
pnpm, eslint, vue-router4, element-plus, pinia
pnpm·pinia·element-plus·暂存区eslint·vue-router4
罗_三金1 个月前
(4)Vue 3 + Vite + Axios + Pinia + Tailwind CSS搭建一个基础框架
前端·css·vue.js·axios·pinia·tailwind
她和夏天一样热2 个月前
【前端系列】Pinia状态管理库
前端·axios·pinia
暂时先用这个名字4 个月前
vue3中mitt和pinia的区别和主要用途,是否有可重合的部分?
开发语言·javascript·vue.js·pinia·组件·通信·mitt
白雾茫茫丶5 个月前
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
postgresql·vue3·vite·pinia·nest.js·prisma
濮水大叔5 个月前
在Vue3中如何实现四种全局状态数据的统一管理?
typescript·vue3·pinia
汤米粥5 个月前
Pinia只能存储简单数据类型
pinia
威哥爱编程6 个月前
Vue状态管理库Pinia详解
javascript·vue·pinia
bjzhang756 个月前
Vue快速入门(六)——Vue3 状态管理 - Pinia(一)
前端·javascript·vue.js·pinia