记录开源项目中点击空白区域关闭一二级菜单的问题

今天在开发TinyEngine华为低代码引擎开源项目时,我遇到了一个细节的问题:原本是点击标题显示菜单,再次点击标题或点击空白区域关闭菜单。中国没错的,然后呢,这里我手动实现了一个二级菜单,二级菜单内部点击是会切换该选项后面跟着的图标的,我希望点击完之后只是图标变化,但点击菜单内部时菜单也会关闭,虽然也能用,但很影响用户体验,这不是我期望的行为。
在这里插入图片描述

简单的描述一下问题就是:
在项目中,我实现了一个点击标题显示菜单的功能,并在点击空白区域时关闭菜单。然而,点击菜单内部时菜单也会关闭,这导致用户体验不佳。

这里先贴一下问题代码段

模板部分
<template>
  <div class="top-panel-logo">
    <h1 class="logo-wrap" @click.stop="handleTitleClick">
      <div class="menu-icon-wrapper">
        <svg-icon name="menu"></svg-icon>
        <span class="menu-title">{{ state.appName }}</span>
      </div>
    </h1>
    <div v-if="state.showMenu" class="main-menu">
      <ul>
        <li @click="handleClick({ code: 'publishApp' })">
          <span class="menu-item">发布应用</span>
        </li>
        <li @mouseenter="state.showSubMenu = true" @mouseleave="state.showSubMenu = false" >
          <span class="menu-item">显示设置</span>
          <icon-right></icon-right>
        </li>
      </ul>
    </div>
  </div>
   <div
      v-if="state.showMenu && state.showSubMenu"
      class="sub-menu"
      @mouseenter="state.showSubMenu = true"
      @mouseleave="state.showSubMenu = false"
    >
      <ul>
        <li v-for="(item, index) in subMenus" :key="index" @click="changeShowState(item)">
          <span class="menu-item">{{ item.name }}</span>
          <span v-show="item.isShow"></span><!--二级选项状态标识-->
        </li>
      </ul>
    </div>
    <!--省略其他内容-->
  </div>
</template>
脚本部分
<script setup>
import ...省略

const state = reactive({
  showMenu: false,
  showSubMenu: false,
});
const subMenus = ref([
  { name: '左侧活动栏', code: 'changeLeft', isShow: true },
  { name: '右侧活动栏', code: 'changeRight', isShow: true },
  { name: '底部活动栏', code: 'changeBottom', isShow: true }
])

const handleCloseMenu = () => {
  state.showMenu = false
  state.showSubMenu = false
  window.removeEventListener('click', handleCloseMenu)
}

const handleTitleClick = () => {
  state.showMenu = !state.showMenu
  if (state.showMenu) {
    window.addEventListener('click', handleCloseMenu)
  } else {
    window.removeEventListener('click', handleCloseMenu)
  }
}

onUnmounted(() => {
  window.removeEventListener('click', handleCloseMenu)
})
</script>

在点击标题时会切换 state.showMenu 的值并在 window 上添加或移除 click 事件监听器,这里是为了在点击空白区域时关闭菜单。
但是!!!!这样会导致点击菜单内部时也会关闭菜单!(在增加显示设置菜单时其实这个是没有影响的,因为增加该需求前,这里原本只有一个发布页面按钮,点击时会弹出悬浮操作框,此时关闭操作栏的逻辑也是没有问题的,但这实际上是触发了window上的事件实现的)

所以问题的根本原因在于 window 上的 click 事件监听器会在点击菜单内部时触发,从而调用 handleCloseMenu 方法关闭菜单
❗💥我们需要一种方法来阻止事件冒泡,使得点击菜单内部时不会触发 window 上的 click 事件。

解决方法

可以使用 Vue.js 的事件修饰符 @click.stop 来阻止事件冒泡,从而防止点击菜单内部时关闭菜单

解决方案步骤

  1. 在菜单的 @click 事件上添加 .stop 修饰符

    <div v-if="state.showMenu" class="main-menu" @click.stop>
      <ul>
        <li @click="handleClick({ code: 'publishApp' })">
          <span class="menu-item">发布应用</span>
        </li>
        <!-- 其他菜单项 -->
      </ul>
    </div>
    

    这样点击菜单内部时事件不会冒泡到 window,就不会触发 handleCloseMenu 方法

  2. 在子菜单的 @click 事件上添加 .stop 修饰符

    如果有子菜单同样需要在子菜单的 @click 事件上添加 .stop 修饰符:

    <div
      v-if="state.showMenu && state.showSubMenu"
      class="sub-menu"
      @mouseenter="state.showSubMenu = true"
      @mouseleave="state.showSubMenu = false"
      @click.stop
    >
      <ul>
        <li v-for="(item, index) in subMenus" :key="index" @click="changeShowState(item)">
          <span class="menu-item">{{ item.name }}</span>
          <span v-show="item.isShow"></span>
        </li>
      </ul>
    </div>
    

    这样点击子菜单内部时,事件同样不会冒泡到 window,就不会触发 handleCloseMenu 方法
    完。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 03:08:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 03:08:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 03:08:02       58 阅读
  4. Python语言-面向对象

    2024-07-19 03:08:02       69 阅读

热门阅读

  1. 定制 Linux 内核的意义

    2024-07-19 03:08:02       18 阅读
  2. 什么是diff算法?

    2024-07-19 03:08:02       17 阅读
  3. 让你写Vue/React更轻松的工具

    2024-07-19 03:08:02       21 阅读
  4. 关系数据库-关系数据库基础概念解析

    2024-07-19 03:08:02       17 阅读
  5. MATLAB并模拟一个质量-弹簧-阻尼系统(pid)

    2024-07-19 03:08:02       20 阅读
  6. 货币转换机器人:金融科技与云计算的融合

    2024-07-19 03:08:02       23 阅读
  7. Nginx的部署、配置和优化

    2024-07-19 03:08:02       25 阅读
  8. 【Pytorch笔记】张量

    2024-07-19 03:08:02       21 阅读
  9. 代码随想录学习 54day 图论 Bellman_ford 算法精讲

    2024-07-19 03:08:02       20 阅读