使用Vue实现一个当鼠标悬浮时出现,鼠标离开时消失的双层菜单

简介: 这篇文章介绍了如何在Vue中实现一个鼠标悬浮时出现、鼠标离开时消失的双层菜单,并提供了详细的代码示例和运行效果展示。

前言

分享一个基于Vue实现一个当鼠标悬浮时出现,鼠标离开时消失的双层菜单。同时也是为了以后需要类似的需求时,可以提供一个实现思路,以及可以快速ctrl+c和ctrl+v操作,提高工作效率~

一、示例代码

(1)/src/views/Example/DiyNavMenu/index.vue

<template>
  <div class="index">
    <ul>
      <li
        v-for="(item, index) in tabList"
        :key="index"
        :class="{ 'active-tab': index == activeTabIndex }"
        @mouseover="
          item.name == '项目管理'
            ? (item.isVisibleMenuBox = true)
            : (item.isVisibleMenuBox = false)
        "
        @mouseleave="
          item.isVisibleMenuBox = false;
          isVisibleSubMenuBox = false;
          isMenuHover = -1;
        "
      >
        <span class="tab-label">{
  
  { item.name }}</span>

        <div class="menu" v-show="item.isVisibleMenuBox">
          <div class="menu-box">
            <div class="menu-box-cascader">
              <div
                class="menu-item"
                v-for="(menuItem, menuIndex) in menuList"
                :key="menuIndex"
                :class="{ 'menu-hover': menuIndex == isMenuHover }"
                @mouseover="handleMenuMouseOver(menuItem, menuIndex)"
              >
                <span>{
  
  { menuItem.label }}</span>
                <i class="el-icon-arrow-right" />
              </div>
            </div>

            <div class="menu-box-cascader" v-show="isVisibleSubMenuBox">
              <div
                class="menu-item"
                v-for="(subMenuItem, subMenuIndex) in subMenuList"
                :key="subMenuIndex"
                @click="handleSubMenuClick(subMenuItem, subMenuIndex)"
              >
                <span>{
  
  { subMenuItem.label }}</span>
              </div>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
    
    
  data: () => ({
    
    
    // 默认激活的页签索引
    activeTabIndex: 1,
    // 页签列表
    tabList: [
      {
    
    
        name: '系统中心',
        isVisibleMenuBox: false,
      },
      {
    
    
        name: '项目管理',
        isVisibleMenuBox: false,
      },
      {
    
    
        name: '用户管理',
        isVisibleMenuBox: false,
      },
    ],
    // 菜单列表
    menuList: [
      {
    
    
        label: '卡拉OK项目工程',
        children: [
          {
    
    
            label: '卡拉一期',
          },
          {
    
    
            label: '卡拉二期',
          },
          {
    
    
            label: '卡拉三期',
          },
          {
    
    
            label: '卡拉四期',
          },
          {
    
    
            label: '卡拉五期',
          },
        ],
      },
      {
    
    
        label: '芭比Q项目工程',
        children: [
          {
    
    
            label: '芭比一期',
          },
          {
    
    
            label: '芭比二期',
          },
        ],
      },
      {
    
    
        label: '最流批的项目工程',
        children: [
          {
    
    
            label: '最流批一期',
          },
        ],
      },
    ],
    // 菜单索引
    isMenuHover: -1,
    // 子菜单是否可见
    isVisibleSubMenuBox: false,
    // 子菜单列表
    subMenuList: [],
  }),
  methods: {
    
    
    /**
     * 菜单鼠标悬浮事件
     */
    handleMenuMouseOver(menuItem, menuIndex) {
    
    
      this.isMenuHover = menuIndex
      if (menuItem.children) {
    
    
        this.isVisibleSubMenuBox = true
        this.subMenuList = menuItem.children
      }
    },

    /**
     * 子菜单点击事件
     */
    handleSubMenuClick(subMenuItem, subMenuIndex) {
    
    
      console.log('handleSubMenuClick ->', subMenuItem, subMenuIndex)
    },
  },
};
</script>

<style lang="less" scoped>
.index {
    
    
  width: 100%;
  height: 35px;
  display: flex;
  justify-content: center;
  background-color: #fff;
  border-bottom: 1px solid #eee;

  ul {
    
    
    min-width: 300px;
    height: 100%;
    display: flex;
    justify-content: space-between;

    li {
    
    
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      list-style: none;
      position: relative;

      .tab-label {
    
    
        padding: 0px 10px;
        font-size: 14px;
        line-height: 34px;
        border-bottom: 1px solid transparent;
      }

      .tab-label:hover {
    
    
        border-bottom: 1px solid #072fbe;
        cursor: pointer;
        color: #072fbe;
      }

      .menu {
    
    
        position: absolute;
        top: 35px;
        left: 0;
        z-index: 10;
        width: 150px;
        height: auto;
        background-color: #fff;

        .menu-box {
    
    
          position: relative;
          display: flex;
          width: 100%;
          height: auto;

          .menu-box-cascader {
    
    
            width: 100%;
            height: 200px;
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 1px 2px 8px 0 rgba(0, 0, 0, 0.15);

            &:nth-of-type(2) {
    
    
              position: absolute;
              top: 0;
              left: 152px;
              width: 180px;
              // background-color: #faf;
            }

            .menu-item {
    
    
              position: relative;
              width: 100%;
              height: 28px;
              display: flex;
              align-items: center;
              justify-content: center;
              cursor: pointer;

              span {
    
    
                font-size: 13px;
              }

              .el-icon-arrow-right {
    
    
                font-size: 12px;
                position: absolute;
                right: 2px;
              }

              &:hover {
    
    
                background-color: #072fbe1a;

                span, .el-icon-arrow-right {
    
    
                  color: #072fbe;
                }
              }
            }

            .menu-hover {
    
    
              background-color: #072fbe1a;

              span, .el-icon-arrow-right {
    
    
                color: #072fbe;
              }
            }
          }
        }
      }
    }

    .active-tab {
    
    
      // background-color: aqua;

      .tab-label {
    
    
        border-bottom: 1px solid #072fbe;
        color: #072fbe;
      }
    }
  }
}
</style>

二、运行效果

目录
相关文章
|
2月前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
148 1
|
7天前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
11天前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
66 12
|
7天前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
7天前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
|
28天前
|
JavaScript 安全 API
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
55 8
|
29天前
|
存储 设计模式 JavaScript
Vue 组件化开发:构建高质量应用的核心
本文深入探讨了 Vue.js 组件化开发的核心概念与最佳实践。
75 1
|
2月前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
3月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
3月前
|
JavaScript 前端开发 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的

热门文章

最新文章