You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular/SCSS通知下拉菜单MouseEnter/MouseLeave问题求助

问题根源与修复方案

你的核心问题是SCSS嵌套结构错误,导致悬停桥接层和下拉菜单的定位基准错误,无法覆盖铃铛与下拉之间的间隙;同时下拉菜单和铃铛之间的额外间隙也加剧了mouseleave触发的问题。以下是具体修复步骤:

关键修复点

  1. 修正SCSS嵌套层级:将.notification-hover-bridge和.notifications-dropdown从.notification-bell的嵌套中移出,放到外层.notification-wrapper下,让它们以整个容器为定位基准。
  2. 消除间隙并衔接桥接层:去掉下拉菜单top属性中的额外间隙,同时让桥接层完全覆盖铃铛到下拉的过渡区域。
  3. 统一显示逻辑:避免Angular事件与CSS hover规则冲突,确保悬停范围统一在外层容器上。

修改后的完整代码

HTML(仅调整容器类绑定,可选)

<div class="notification-wrapper" 
     (mouseenter)="showDropdown = true"
     (mouseleave)="showDropdown = false"
     [class.show-dropdown]="showDropdown">

  <!-- Notification Bell -->
  <div class="notification-bell" [attr.data-count]="getUnreadCount()">
    🔔 {{ getUnreadCount() }}
  </div>

  <!-- Hover Bridge -->
  <div class="notification-hover-bridge"></div>

  <!-- Dropdown -->
  <ul class="notifications-dropdown">
    <li class="mark-all-container" *ngIf="notifications.length > 0">
      <span>Notifications</span>
      <button (click)="markAllAsRead()">Mark All as Read</button>
    </li>
    <li *ngFor="let n of notifications">
      <a *ngIf="n.link" [routerLink]="n.link" (click)="markAsRead(n.id)">
        {{ n.message }}
      </a>
      <span *ngIf="!n.link">{{ n.message }}</span>
      <button (click)="markAsRead(n.id)">Mark as Read</button>
    </li>
    <li *ngIf="notifications.length === 0">
      No notifications yet!
    </li>
  </ul>
</div>
<button *ngIf="loggedIn" (click)="goToMyShit()" class="btn btn-warning">💩 My Shit</button>

SCSS(核心结构调整)

.notification-wrapper {
  position: relative;
  display: inline-block;
  z-index: 1000;

  .notification-bell {
    position: relative;
    display: inline-block;
    font-size: 1.5rem;
    color: #ff0;
    cursor: pointer;
    text-shadow: 0 0 10px #ff0, 0 0 20px #ff0;
    transition: transform 0.2s ease-in-out;

    &:hover {
      transform: scale(1.1);
    }

    &::after {
      content: attr(data-count);
      position: absolute;
      top: -8px;
      right: -12px;
      background-color: #f00;
      color: white;
      font-size: 0.7rem;
      font-weight: bold;
      padding: 4px 6px;
      border-radius: 50%;
      box-shadow: 0 0 10px #f00, 0 0 20px #f00;
      z-index: 10;
    }
  }

  // 悬停桥接层:覆盖铃铛到下拉的过渡区域
  .notification-hover-bridge {
    position: absolute;
    top: 100%;
    left: 0;
    width: 100%;
    height: 15px; // 可根据实际间隙调整高度
    z-index: 999;
    // 调试时可开启背景色查看覆盖范围:background: rgba(255,0,0,0.2);
  }

  .notifications-dropdown {
    display: none;
    position: absolute;
    top: 100%; // 去掉+2px间隙,与桥接层无缝衔接
    left: 50%;
    transform: translate(-50%);
    width: 300px;
    max-height: 400px;
    overflow-y: auto;
    background: #1a1a1a;
    border: 2px solid #ff00ff;
    border-radius: 10px;
    padding: 0;
    margin: 0;
    list-style: none;
    z-index: 1001;
    box-shadow: 0 0 20px #ff00ff, 0 0 30px #ff00ff;

    .mark-all-container {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 16px;
      background: #2a2a2a;
      border-bottom: 2px solid #ff00ff;
      color: #ff0;
      font-weight: bold;
      font-size: 1rem;
      text-shadow: 0 0 10px #ff0;

      button {
        background: none;
        border: 1px solid #ff0;
        color: #ff0;
        padding: 4px 10px;
        font-size: 0.75rem;
        border-radius: 5px;
        text-shadow: 0 0 5px #ff0;
        box-shadow: 0 0 10px #ff0;
        cursor: pointer;
        transition: all 0.3s ease;

        &:hover {
          background-color: #ff0;
          color: #121212;
          box-shadow: 0 0 20px #ff0, 0 0 40px #ff0;
        }
      }
    }

    li {
      padding: 10px 16px;
      border-bottom: 1px solid #333;
      display: flex;
      justify-content: space-between;
      align-items: center;
      font-size: 0.95rem;
      color: #fff;
      text-shadow: 0 0 5px #0f0;
      transition: background-color 0.3s;

      &:hover {
        background-color: #2a2a2a;
      }

      button {
        background: none;
        border: 1px solid #0ff;
        padding: 4px 8px;
        color: #0ff;
        border-radius: 6px;
        font-size: 0.75rem;
        cursor: pointer;
        text-shadow: 0 0 5px #0ff;
        box-shadow: 0 0 10px #0ff;
        transition: all 0.3s ease;

        &:hover {
          background-color: #0ff;
          color: #121212;
          box-shadow: 0 0 20px #0ff, 0 0 40px #0ff;
        }
      }
    }

    li:last-child {
      border-bottom: none;
    }
  }

  // 两种触发逻辑二选一即可,推荐保留CSS hover简化代码
  &:hover .notifications-dropdown,
  &.show-dropdown .notifications-dropdown {
    display: block;
  }
}

额外调试技巧

可以给.notification-hover-bridge临时添加半透明背景色(如background: rgba(255,0,0,0.2)),直观查看它的覆盖范围,调整height值直到完全覆盖铃铛与下拉之间的间隙。

内容的提问来源于stack exchange,提问作者user22330338

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:48:12