el-menu + el-badge 菜单加红点标识el-badge

文章讲述了如何在Vue项目中使用el-menu组件实现菜单项的动态红点标识,通过Vuex管理状态并结合API调用来更新待办数量,同时实现路由变化时菜单的自动刷新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


main.js引入全局组件
el-menu封装

一、el-menu组件

menu/index.vue

重点:定义 ref="menu",切换路由时调用 refreshs() 更新组件

<template>
  <el-menu :unique-opened="true" :default-active="this.$store.state.menuData.menuActive" class="el-menu-vertical-demo" :background-color="backgroundColor" :text-color="textColor" :active-text-color="activeTextColor">
    <subMenu ref="menu" :menuList="sideNavMenu" :key="Math.random()"></subMenu>
  </el-menu>
</template>

<script>

import { getMenuBadgeApi } from '@/common/js/api'

export default {
  name: "index",
  props: {},
  data() {
    return {
      backgroundColor: "#EAEEF6",
      textColor: "#3F434E",
      activeTextColor: "#2A60CC",
      sideNavMenu: this.$store.state.menuData.sideNavMenu,

      // 登录人筛选后的菜单红点标识
      hasBadgeMenu: null,
      // 菜单红点标识定义
      badgeItem: {
        // 第一个参数是 hasBadgeMenu 下 obj 下标(pObjOrder)
        // 第二个参数是 obj 中 child 中的 obj 下标(cObjOrder)
        // 第三个参数是调用的接口
        '/home': [0, 0, 'getMenuHomeBadgeApi'], // 首页待办数量
        '/about': [0, 1, 'getMenuHomeBadgeApi'], // 关于页待办数量
      },

    }
  },
  mounted() {
    this.reshsMenu()
  },
  methods: {
    // 重塑menu
    async reshsMenu() {
      await this.getMenuBadge()
      this.$refs.menu.reshsMenu();
    },
    // 更新菜单红点标识
    async getMenuBadge() {
      // 获取vuex中的菜单
      let sideMenu = this.$store.state.menuData.sideNavMenu

      // badge = [
      //   {
      //     item:{ },
      //     child:[
      //       { item: {}, api: 'home_examineHouseholdCount' },
      //       { item: {}, api: 'home_examineConsumptionCount' },
      //     ]
      //   }
      // ]

      // 过滤登录人所需菜单红点标识
      if (!this.hasBadgeMenu) {
        this.hasBadgeMenu = []
        sideMenu.forEach(item => {
          if (!!item.children) {
            item.children.forEach(cItem => {
              for (var key of Object.keys(this.badgeItem)) {
                if (cItem.path === key) {
                  let pObjOrder = this.badgeItem[key][0]
                  if (!this.hasBadgeMenu[pObjOrder]) {
                    this.hasBadgeMenu[pObjOrder] = {}
                  }
                  if (!this.hasBadgeMenu[pObjOrder].child) {
                    this.hasBadgeMenu[pObjOrder].child = []
                  }
                  let cObjOrder = this.badgeItem[key][1]
                  if (!this.hasBadgeMenu[pObjOrder].child[cObjOrder]) {
                    this.hasBadgeMenu[pObjOrder].child[cObjOrder] = {}
                  }
                  this.hasBadgeMenu[pObjOrder].child[cObjOrder].item = cItem
                  this.hasBadgeMenu[pObjOrder].child[cObjOrder].api = this.badgeItem[key][2]
                  this.hasBadgeMenu[pObjOrder].item = item
                }
              }
            })
          }
          else { }
        })
      }

      // 调用红点信息接口
      for (let i in this.hasBadgeMenu) {
        if (this.hasBadgeMenu[i]) {
          for (let j in this.hasBadgeMenu[i].child)
            if (this.hasBadgeMenu[i].child[j]) {
              if (getMenuBadgeApi[this.hasBadgeMenu[i].child[j].api]) {
                await getMenuBadgeApi[this.hasBadgeMenu[i].child[j].api]().then(res => {
                  this.hasBadgeMenu[i].child[j].item.badgeNum = res.data
                })
              } else {
                console.error('接口未定义');
              }
            }
        }
      }

      // 判断父级标识
      for (let j in this.hasBadgeMenu) {
        // this.hasBadgeMenu[j].item.showBadge = false;
        this.hasBadgeMenu[j].item.badgeNum = 0;
        for (let i in this.hasBadgeMenu[j].child) {
          if (!!this.hasBadgeMenu[j].child[i].item.badgeNum) {
            // this.hasBadgeMenu[j].item.showBadge = true;
            // break
            this.hasBadgeMenu[j].item.badgeNum += this.hasBadgeMenu[j].child[i].item.badgeNum
          }
        }
      }

      this.$store.commit("menuData/change_sideNavMenu", sideMenu);

    },
  },
  watch: {
    $route(to, from) {
      this.reshsMenu()
    },
  },
  created() { },
}
</script>

menu/submenu.vue

重点:定义ref="subMenu",调用 refreshs() 更新组件,el-badge 展示标识未处理数据数量
<el-badge v-if="!!list.badgeNum" :value="list.badgeNum" :max="99"> </el-badge>

<template>
  <div>
    <div v-for="(list,index) in this.menuList" :key="index">

      <el-submenu v-if="!!list.children" :key="list.id" :index="String(list.id)">
        <template slot="title">
          <i class="menu_icon" :class="list.icon"></i>
          <span slot="title">{{ list.name}}</span>
          <el-badge v-if="!!list.badgeNum" :value="list.badgeNum" :max="99"> </el-badge>
          <!-- <el-badge v-if="list.showBadge" value="new"> </el-badge> -->
        </template>
        <subMenu ref="subMenu" :menuList="list.children"></subMenu>
      </el-submenu>
      <el-menu-item v-else :index="list.path">
        <router-link :target="targeLink(list.path)?'_blank':''" :to="list.path">
          <i class="menu_icon" :class="list.icon"></i>
          <span>{{list.name}}</span>
          <el-badge v-if="!!list.badgeNum" :value="list.badgeNum" :max="99"> </el-badge>
        </router-link>
      </el-menu-item>

    </div>
  </div>
</template>

<script>
export default {
  name: "submenu",
  data() {
    return {}
  },
  props: {
    menuList: Array
  },
  mounted() { },
  methods: {
    targeLink(path) {
      if (path === '/aboutUs') {
        return true
      } else {
        return false
      }
    },
    // 重塑menu
    refreshs() {
      this.$forceUpdate()
      if (this.$refs.subMenu) {
        this.$refs.subMenu.forEach(item => {
          item.refreshs()
        })
      }
    },
  },
  watch: {},
  created() { },
}
</script>

二、获取/更新菜单红点标识

调用 getMenuBadge() 获取/更新待办数据(红点显示数据)
api.js

import { getOneOrAllData } from '@/common/js/http'
// 菜单接口
export const getMenuListApi = p => getOneOrAllData('/getMenuListApi', p)
// 菜单角标数据接口
export const getMenuBadgeApi = {
  getMenuHomeBadgeApi: p => getOneOrAllData('/getMenuHomeBadgeApi ', p),//首页待办数量
  getMenuAboutBadgeApi: p => getOneOrAllData('/getMenuAboutBadgeApi', p),//关于页待办数量
};

main.js定义全局变量

// 定义全局变量
const globalData = Vue.observable({
  refMenu: ''
});
Vue.prototype.globalData = globalData

调用组件,给全局变量赋值

<Menu ref="menu"></Menu>
this.globalData.refMenu = this.$refs['menu']

使用同步更新待办标识async...await...

api.then(async res => {
	await this.globalData.refMenu.reshsMenu()
})

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值