vue实现鼠标移入动态展示导航栏二级菜单(异步)

文章介绍了如何通过在HTML中使用`onmouseover`和`onmouseout`事件以及JavaScript的防抖函数(debounce)来控制元素在鼠标快速移动时避免闪烁,提供了一个示例代码,展示了如何在导航菜单中实现平滑的二级菜单显示和隐藏,以提升用户体验。
摘要由CSDN通过智能技术生成

# 因使用hover如果频率移入太快,导致元素出现闪动的情况,所以可以通过鼠标移入移出事件来控制,上代码:

1、鼠标移入事件:onmouseover

2、鼠标移出事件:onmouseout

4、鼠标进入事件:onmouseenter

5、鼠标离开事件:onmouseleave

一.、HTML部分:

          <div class="menu-list-wrap">
            <ul class="menu_list">
              <li class="menus_item" v-for="(item, index) in menuDataTest" :key="index"
                @mouseover="showSubmenu(item, index)" @mouseout="hideSubmenu(index)">
                <div class="menu_item_name">{{ item.name }}</div>
                <div class="secondary-menu" v-show="item.columns.length > 0 && showSubMenu && activeSubmenu === index">
                  <div class="menu-wrap" v-for="(column, columnIndex) in item.columns" :key="columnIndex">
                    <span>{{ column.name }}</span>
                  </div>
                </div>
              </li>
            </ul>
          </div>

 二、 js部分

export default {
  data() {
    return {
      menuDataTest: [
        {
          name: '导航1',
          columns: [
            {
              name: '导航1二级菜单1111',
            },
            {
              name: '导航1二级菜单222',
            },
            {
              name: '导航1二级菜单1111',
            }
          ],
        },
        {
          name: '导航2',
          columns: [
            {
              name: '导航2二级菜单1111',
            },
            {
              name: '导航2二级菜单222',
            },
            {
              name: '导航2二级菜单1111',
            }
          ],
        },
        {
          name: '导航3',
          columns: [
            {
              name: '导航3二级菜单1111',
            },
            {
              name: '导航3二级菜单222',
            },
            {
              name: '导航3二级菜单1111',
            }
          ],
        },
        {
          name: '导航4',
          columns: [
            {
              name: '导航4二级菜单1111',
            },
            {
              name: '导航4二级菜单222',
            },
            {
              name: '导航4二级菜单1111',
            }
          ],
        },
      ],

      menuTimer: null, // 定时器
      activeSubmenu: null, // 当前要展示的菜单
      showSubMenu: false, // 控制二级菜单显示隐藏值

},
methods: {
    // 鼠标移入
    showSubmenu(item, index) {
      const _this = this;
      clearTimeout(_this.menuTimer)
      if (item.columns && item.columns.length > 0) {
        _debounce(function () {
          _this.activeSubmenu = index;
          _this.showSubMenu = true
        }, 200);
      }

    },

    // 鼠标移出
    hideSubmenu(index) {
      const _this = this;
      if (_this.activeSubmenu === index) {
        _this.menuTimer = setTimeout(() => {
          _this.activeSubmenu = null;
          _this.showSubMenu = false
        }, 200)
      }
    },
}

三.、css部分:

/** 菜单区域 */
.menu-list-wrap {
  display: inline-block;
  line-height: 80px;
  vertical-align: top;
  text-align: center;
}

.menu_list {
  display: flex;
  justify-content: space-between;

  .menu_item_name {
    font-family: "微软雅黑 Bold", "微软雅黑 Regular", "微软雅黑", sans-serif;
    display: inline-block;
    color: #333;
    font-weight: 400;
    font-style: normal;
    margin: 0 16px;
    cursor: pointer;
    height: 80px;
  }
}

.menu_item_name:after {
  display: block;
  content: "";
  height: 4px;
  width: 64px;
  position: absolute;
  bottom: 0;
  margin: 0 auto;
  background: #005CD8;
  opacity: 0;
  transition: transform 0.2s ease-out, opacity 0.2s ease-out;
  transform-origin: 50% 50%;
  transform: scale(0.01, 1);
}

.menus_item:hover .menu_item_name:after {
  transform: scale(1, 1);
  opacity: 1;
}

.menus_item:hover .menu_item_name {
  color: #005CD8;
  font-weight: 700;
}

.secondary-menu {
  display: flex;
  flex-direction: row;
  justify-content: center;
  width: 100vw;
  position: fixed;
  left: 0px;
  z-index: 2;
  background: #fff;
  box-shadow: 0 4px 10px 0 rgb(0 0 0 / 10%);
  animation: secondary-menu-show 0.2s ease-out both;
  text-align: left;
  padding: 0 100px 0 80px;
}

.menu-wrap {
  flex: 1;
  margin: 25px;
  animation: secondary-menu-show 0.3s ease-out both;
}

四、 优化:这里使用了防抖函数,为了防止频繁操作

/* 防抖函数 */
let timeoutValue = null // 创建一个标记用来存放定时器的返回值
let countValue = 0;
export function _debounce(fn, wait = 1000, immediate = false) {
  return function () {
    const args = arguments;
    if (immediate) {
      if (countValue == 0) {
        fn.apply(this, arguments)
        countValue++;
      } else {
        if (timeoutValue) {
          clearTimeout(timeoutValue) // 每当用户输入的时候把前一个 setTimeout clear 掉
        }

        timeoutValue = setTimeout(() => {
          fn.apply(this, arguments)
        }, wait)
      }
    } else {
      if (timeoutValue) {
        clearTimeout(timeoutValue) // 每当用户输入的时候把前一个 setTimeout clear 掉
      }
      timeoutValue = setTimeout(() => {
        fn.apply(this, arguments)
      }, wait)
    }

  }()
}

总结:这里只是简单的小例子,具体样式还需根据项目实现,次代码可解决频繁移入事件中展示不同的东西使用,做了异步和频繁移入处理,防止出现闪屏情况,影响用户体验。

在Ant Design Vue中,可以使用Menu组件来实现左侧一级菜单和右侧导航二三级菜单的布局。下面是一个简单的代码示例: ```vue <template> <div> <a-layout style="min-height: 100vh"> <a-layout-sider :width="200"> <a-menu mode="inline" :default-selected-keys="['1']"> <a-menu-item key="1"> <a-icon type="user" /> <span>菜单1</span> </a-menu-item> <a-menu-item key="2"> <a-icon type="video-camera" /> <span>菜单2</span> </a-menu-item> <a-sub-menu key="sub1"> <template slot="title"> <a-icon type="mail" /> <span>菜单3</span> </template> <a-menu-item key="3">子菜单1</a-menu-item> <a-menu-item key="4">子菜单2</a-menu-item> </a-sub-menu> </a-menu> </a-layout-sider> <a-layout-content style="padding: 24px"> <!-- 右侧内容 --> </a-layout-content> </a-layout> </div> </template> <script> export default { name: 'YourComponent', // 其他组件配置 } </script> <style scoped> /* 样式定义 */ </style> ``` 在上面的代码中,我们使用了Ant Design Vue的Layout、Menu和Icon组件来实现左侧一级菜单和右侧导航二三级菜单的布局。其中,Layout组件用于整体布局,LayoutSider组件用于左侧菜单栏,LayoutContent组件用于右侧内容区域。Menu组件用于定义菜单项,可以通过设置mode属性来指定菜单的展示方式,通过设置default-selected-keys属性来指定默认选中的菜单项。 相关问题: 1. Ant Design Vue中如何实现左侧一级菜单和右侧导航二三级菜单的布局? 2. 如何在Ant Design Vue中定义菜单项? 3. 如何设置Ant Design Vue菜单的默认选中项? 4. Ant Design Vue中的Layout组件有哪些常用属性和方法? 5. 如何在Ant Design Vue中使用Icon图标?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值